1 2 /* 3 Defines the basic matrix operations for the AIJ (compressed row) 4 matrix storage format. 5 */ 6 7 8 #include <../src/mat/impls/aij/seq/aij.h> /*I "petscmat.h" I*/ 9 #include <petscblaslapack.h> 10 #include <petscbt.h> 11 #include <petsc/private/kernels/blocktranspose.h> 12 13 PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A) 14 { 15 PetscErrorCode ierr; 16 PetscBool flg; 17 char type[256]; 18 19 PetscFunctionBegin; 20 ierr = PetscObjectOptionsBegin((PetscObject)A); 21 ierr = PetscOptionsFList("-mat_seqaij_type","Matrix SeqAIJ type","MatSeqAIJSetType",MatSeqAIJList,"seqaij",type,256,&flg);CHKERRQ(ierr); 22 if (flg) { 23 ierr = MatSeqAIJSetType(A,type);CHKERRQ(ierr); 24 } 25 ierr = PetscOptionsEnd();CHKERRQ(ierr); 26 PetscFunctionReturn(0); 27 } 28 29 PetscErrorCode MatGetColumnNorms_SeqAIJ(Mat A,NormType type,PetscReal *norms) 30 { 31 PetscErrorCode ierr; 32 PetscInt i,m,n; 33 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 34 35 PetscFunctionBegin; 36 ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr); 37 ierr = PetscArrayzero(norms,n);CHKERRQ(ierr); 38 if (type == NORM_2) { 39 for (i=0; i<aij->i[m]; i++) { 40 norms[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]); 41 } 42 } else if (type == NORM_1) { 43 for (i=0; i<aij->i[m]; i++) { 44 norms[aij->j[i]] += PetscAbsScalar(aij->a[i]); 45 } 46 } else if (type == NORM_INFINITY) { 47 for (i=0; i<aij->i[m]; i++) { 48 norms[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),norms[aij->j[i]]); 49 } 50 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown NormType"); 51 52 if (type == NORM_2) { 53 for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]); 54 } 55 PetscFunctionReturn(0); 56 } 57 58 PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A,IS *is) 59 { 60 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 61 PetscInt i,m=A->rmap->n,cnt = 0, bs = A->rmap->bs; 62 const PetscInt *jj = a->j,*ii = a->i; 63 PetscInt *rows; 64 PetscErrorCode ierr; 65 66 PetscFunctionBegin; 67 for (i=0; i<m; i++) { 68 if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) { 69 cnt++; 70 } 71 } 72 ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr); 73 cnt = 0; 74 for (i=0; i<m; i++) { 75 if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) { 76 rows[cnt] = i; 77 cnt++; 78 } 79 } 80 ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,is);CHKERRQ(ierr); 81 PetscFunctionReturn(0); 82 } 83 84 PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A,PetscInt *nrows,PetscInt **zrows) 85 { 86 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 87 const MatScalar *aa = a->a; 88 PetscInt i,m=A->rmap->n,cnt = 0; 89 const PetscInt *ii = a->i,*jj = a->j,*diag; 90 PetscInt *rows; 91 PetscErrorCode ierr; 92 93 PetscFunctionBegin; 94 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 95 diag = a->diag; 96 for (i=0; i<m; i++) { 97 if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) { 98 cnt++; 99 } 100 } 101 ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr); 102 cnt = 0; 103 for (i=0; i<m; i++) { 104 if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) { 105 rows[cnt++] = i; 106 } 107 } 108 *nrows = cnt; 109 *zrows = rows; 110 PetscFunctionReturn(0); 111 } 112 113 PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows) 114 { 115 PetscInt nrows,*rows; 116 PetscErrorCode ierr; 117 118 PetscFunctionBegin; 119 *zrows = NULL; 120 ierr = MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows);CHKERRQ(ierr); 121 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr); 122 PetscFunctionReturn(0); 123 } 124 125 PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows) 126 { 127 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 128 const MatScalar *aa; 129 PetscInt m=A->rmap->n,cnt = 0; 130 const PetscInt *ii; 131 PetscInt n,i,j,*rows; 132 PetscErrorCode ierr; 133 134 PetscFunctionBegin; 135 *keptrows = 0; 136 ii = a->i; 137 for (i=0; i<m; i++) { 138 n = ii[i+1] - ii[i]; 139 if (!n) { 140 cnt++; 141 goto ok1; 142 } 143 aa = a->a + ii[i]; 144 for (j=0; j<n; j++) { 145 if (aa[j] != 0.0) goto ok1; 146 } 147 cnt++; 148 ok1:; 149 } 150 if (!cnt) PetscFunctionReturn(0); 151 ierr = PetscMalloc1(A->rmap->n-cnt,&rows);CHKERRQ(ierr); 152 cnt = 0; 153 for (i=0; i<m; i++) { 154 n = ii[i+1] - ii[i]; 155 if (!n) continue; 156 aa = a->a + ii[i]; 157 for (j=0; j<n; j++) { 158 if (aa[j] != 0.0) { 159 rows[cnt++] = i; 160 break; 161 } 162 } 163 } 164 ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr); 165 PetscFunctionReturn(0); 166 } 167 168 PetscErrorCode MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is) 169 { 170 PetscErrorCode ierr; 171 Mat_SeqAIJ *aij = (Mat_SeqAIJ*) Y->data; 172 PetscInt i,m = Y->rmap->n; 173 const PetscInt *diag; 174 MatScalar *aa = aij->a; 175 const PetscScalar *v; 176 PetscBool missing; 177 178 PetscFunctionBegin; 179 if (Y->assembled) { 180 ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,NULL);CHKERRQ(ierr); 181 if (!missing) { 182 diag = aij->diag; 183 ierr = VecGetArrayRead(D,&v);CHKERRQ(ierr); 184 if (is == INSERT_VALUES) { 185 for (i=0; i<m; i++) { 186 aa[diag[i]] = v[i]; 187 } 188 } else { 189 for (i=0; i<m; i++) { 190 aa[diag[i]] += v[i]; 191 } 192 } 193 ierr = VecRestoreArrayRead(D,&v);CHKERRQ(ierr); 194 PetscFunctionReturn(0); 195 } 196 ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr); 197 } 198 ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr); 199 PetscFunctionReturn(0); 200 } 201 202 PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool *done) 203 { 204 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 205 PetscErrorCode ierr; 206 PetscInt i,ishift; 207 208 PetscFunctionBegin; 209 *m = A->rmap->n; 210 if (!ia) PetscFunctionReturn(0); 211 ishift = 0; 212 if (symmetric && !A->structurally_symmetric) { 213 ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr); 214 } else if (oshift == 1) { 215 PetscInt *tia; 216 PetscInt nz = a->i[A->rmap->n]; 217 /* malloc space and add 1 to i and j indices */ 218 ierr = PetscMalloc1(A->rmap->n+1,&tia);CHKERRQ(ierr); 219 for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1; 220 *ia = tia; 221 if (ja) { 222 PetscInt *tja; 223 ierr = PetscMalloc1(nz+1,&tja);CHKERRQ(ierr); 224 for (i=0; i<nz; i++) tja[i] = a->j[i] + 1; 225 *ja = tja; 226 } 227 } else { 228 *ia = a->i; 229 if (ja) *ja = a->j; 230 } 231 PetscFunctionReturn(0); 232 } 233 234 PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool *done) 235 { 236 PetscErrorCode ierr; 237 238 PetscFunctionBegin; 239 if (!ia) PetscFunctionReturn(0); 240 if ((symmetric && !A->structurally_symmetric) || oshift == 1) { 241 ierr = PetscFree(*ia);CHKERRQ(ierr); 242 if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);} 243 } 244 PetscFunctionReturn(0); 245 } 246 247 PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool *done) 248 { 249 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 250 PetscErrorCode ierr; 251 PetscInt i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n; 252 PetscInt nz = a->i[m],row,*jj,mr,col; 253 254 PetscFunctionBegin; 255 *nn = n; 256 if (!ia) PetscFunctionReturn(0); 257 if (symmetric) { 258 ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr); 259 } else { 260 ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr); 261 ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr); 262 ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr); 263 jj = a->j; 264 for (i=0; i<nz; i++) { 265 collengths[jj[i]]++; 266 } 267 cia[0] = oshift; 268 for (i=0; i<n; i++) { 269 cia[i+1] = cia[i] + collengths[i]; 270 } 271 ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr); 272 jj = a->j; 273 for (row=0; row<m; row++) { 274 mr = a->i[row+1] - a->i[row]; 275 for (i=0; i<mr; i++) { 276 col = *jj++; 277 278 cja[cia[col] + collengths[col]++ - oshift] = row + oshift; 279 } 280 } 281 ierr = PetscFree(collengths);CHKERRQ(ierr); 282 *ia = cia; *ja = cja; 283 } 284 PetscFunctionReturn(0); 285 } 286 287 PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool *done) 288 { 289 PetscErrorCode ierr; 290 291 PetscFunctionBegin; 292 if (!ia) PetscFunctionReturn(0); 293 294 ierr = PetscFree(*ia);CHKERRQ(ierr); 295 ierr = PetscFree(*ja);CHKERRQ(ierr); 296 PetscFunctionReturn(0); 297 } 298 299 /* 300 MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from 301 MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output 302 spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ() 303 */ 304 PetscErrorCode MatGetColumnIJ_SeqAIJ_Color(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool *done) 305 { 306 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 307 PetscErrorCode ierr; 308 PetscInt i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n; 309 PetscInt nz = a->i[m],row,mr,col,tmp; 310 PetscInt *cspidx; 311 const PetscInt *jj; 312 313 PetscFunctionBegin; 314 *nn = n; 315 if (!ia) PetscFunctionReturn(0); 316 317 ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr); 318 ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr); 319 ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr); 320 ierr = PetscMalloc1(nz,&cspidx);CHKERRQ(ierr); 321 jj = a->j; 322 for (i=0; i<nz; i++) { 323 collengths[jj[i]]++; 324 } 325 cia[0] = oshift; 326 for (i=0; i<n; i++) { 327 cia[i+1] = cia[i] + collengths[i]; 328 } 329 ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr); 330 jj = a->j; 331 for (row=0; row<m; row++) { 332 mr = a->i[row+1] - a->i[row]; 333 for (i=0; i<mr; i++) { 334 col = *jj++; 335 tmp = cia[col] + collengths[col]++ - oshift; 336 cspidx[tmp] = a->i[row] + i; /* index of a->j */ 337 cja[tmp] = row + oshift; 338 } 339 } 340 ierr = PetscFree(collengths);CHKERRQ(ierr); 341 *ia = cia; 342 *ja = cja; 343 *spidx = cspidx; 344 PetscFunctionReturn(0); 345 } 346 347 PetscErrorCode MatRestoreColumnIJ_SeqAIJ_Color(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool *done) 348 { 349 PetscErrorCode ierr; 350 351 PetscFunctionBegin; 352 ierr = MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr); 353 ierr = PetscFree(*spidx);CHKERRQ(ierr); 354 PetscFunctionReturn(0); 355 } 356 357 PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[]) 358 { 359 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 360 PetscInt *ai = a->i; 361 PetscErrorCode ierr; 362 363 PetscFunctionBegin; 364 ierr = PetscArraycpy(a->a+ai[row],v,ai[row+1]-ai[row]);CHKERRQ(ierr); 365 PetscFunctionReturn(0); 366 } 367 368 /* 369 MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions 370 371 - a single row of values is set with each call 372 - no row or column indices are negative or (in error) larger than the number of rows or columns 373 - the values are always added to the matrix, not set 374 - no new locations are introduced in the nonzero structure of the matrix 375 376 This does NOT assume the global column indices are sorted 377 378 */ 379 380 #include <petsc/private/isimpl.h> 381 PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is) 382 { 383 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 384 PetscInt low,high,t,row,nrow,i,col,l; 385 const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j; 386 PetscInt lastcol = -1; 387 MatScalar *ap,value,*aa = a->a; 388 const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices; 389 390 row = ridx[im[0]]; 391 rp = aj + ai[row]; 392 ap = aa + ai[row]; 393 nrow = ailen[row]; 394 low = 0; 395 high = nrow; 396 for (l=0; l<n; l++) { /* loop over added columns */ 397 col = cidx[in[l]]; 398 value = v[l]; 399 400 if (col <= lastcol) low = 0; 401 else high = nrow; 402 lastcol = col; 403 while (high-low > 5) { 404 t = (low+high)/2; 405 if (rp[t] > col) high = t; 406 else low = t; 407 } 408 for (i=low; i<high; i++) { 409 if (rp[i] == col) { 410 ap[i] += value; 411 low = i + 1; 412 break; 413 } 414 } 415 } 416 return 0; 417 } 418 419 PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is) 420 { 421 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 422 PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N; 423 PetscInt *imax = a->imax,*ai = a->i,*ailen = a->ilen; 424 PetscErrorCode ierr; 425 PetscInt *aj = a->j,nonew = a->nonew,lastcol = -1; 426 MatScalar *ap=NULL,value=0.0,*aa = a->a; 427 PetscBool ignorezeroentries = a->ignorezeroentries; 428 PetscBool roworiented = a->roworiented; 429 430 PetscFunctionBegin; 431 for (k=0; k<m; k++) { /* loop over added rows */ 432 row = im[k]; 433 if (row < 0) continue; 434 #if defined(PETSC_USE_DEBUG) 435 if (row >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1); 436 #endif 437 rp = aj + ai[row]; 438 if (!A->structure_only) ap = aa + ai[row]; 439 rmax = imax[row]; nrow = ailen[row]; 440 low = 0; 441 high = nrow; 442 for (l=0; l<n; l++) { /* loop over added columns */ 443 if (in[l] < 0) continue; 444 #if defined(PETSC_USE_DEBUG) 445 if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1); 446 #endif 447 col = in[l]; 448 if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m]; 449 if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue; 450 451 if (col <= lastcol) low = 0; 452 else high = nrow; 453 lastcol = col; 454 while (high-low > 5) { 455 t = (low+high)/2; 456 if (rp[t] > col) high = t; 457 else low = t; 458 } 459 for (i=low; i<high; i++) { 460 if (rp[i] > col) break; 461 if (rp[i] == col) { 462 if (!A->structure_only) { 463 if (is == ADD_VALUES) { 464 ap[i] += value; 465 (void)PetscLogFlops(1.0); 466 } 467 else ap[i] = value; 468 } 469 low = i + 1; 470 goto noinsert; 471 } 472 } 473 if (value == 0.0 && ignorezeroentries && row != col) goto noinsert; 474 if (nonew == 1) goto noinsert; 475 if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col); 476 if (A->structure_only) { 477 MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar); 478 } else { 479 MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar); 480 } 481 N = nrow++ - 1; a->nz++; high++; 482 /* shift up all the later entries in this row */ 483 ierr = PetscArraymove(rp+i+1,rp+i,N-i+1);CHKERRQ(ierr); 484 rp[i] = col; 485 if (!A->structure_only){ 486 ierr = PetscArraymove(ap+i+1,ap+i,N-i+1);CHKERRQ(ierr); 487 ap[i] = value; 488 } 489 low = i + 1; 490 A->nonzerostate++; 491 noinsert:; 492 } 493 ailen[row] = nrow; 494 } 495 PetscFunctionReturn(0); 496 } 497 498 PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is) 499 { 500 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 501 PetscInt *rp,k,row; 502 PetscInt *ai = a->i,*ailen = a->ilen; 503 PetscErrorCode ierr; 504 PetscInt *aj = a->j; 505 MatScalar *aa = a->a,*ap; 506 507 PetscFunctionBegin; 508 for (k=0; k<m; k++) { /* loop over added rows */ 509 row = im[k]; 510 rp = aj + ai[row]; 511 ap = aa + ai[row]; 512 if (!A->was_assembled) { 513 ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr); 514 } 515 if (!A->structure_only) { 516 if (v) { 517 ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr); 518 v += n; 519 } else { 520 ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr); 521 } 522 } 523 ailen[row] = n; 524 a->nz += n; 525 } 526 PetscFunctionReturn(0); 527 } 528 529 530 PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[]) 531 { 532 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 533 PetscInt *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j; 534 PetscInt *ai = a->i,*ailen = a->ilen; 535 MatScalar *ap,*aa = a->a; 536 537 PetscFunctionBegin; 538 for (k=0; k<m; k++) { /* loop over rows */ 539 row = im[k]; 540 if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */ 541 if (row >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1); 542 rp = aj + ai[row]; ap = aa + ai[row]; 543 nrow = ailen[row]; 544 for (l=0; l<n; l++) { /* loop over columns */ 545 if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */ 546 if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1); 547 col = in[l]; 548 high = nrow; low = 0; /* assume unsorted */ 549 while (high-low > 5) { 550 t = (low+high)/2; 551 if (rp[t] > col) high = t; 552 else low = t; 553 } 554 for (i=low; i<high; i++) { 555 if (rp[i] > col) break; 556 if (rp[i] == col) { 557 *v++ = ap[i]; 558 goto finished; 559 } 560 } 561 *v++ = 0.0; 562 finished:; 563 } 564 } 565 PetscFunctionReturn(0); 566 } 567 568 569 PetscErrorCode MatView_SeqAIJ_Binary(Mat A,PetscViewer viewer) 570 { 571 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 572 PetscErrorCode ierr; 573 PetscInt i,*col_lens; 574 int fd; 575 FILE *file; 576 577 PetscFunctionBegin; 578 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 579 ierr = PetscMalloc1(4+A->rmap->n,&col_lens);CHKERRQ(ierr); 580 581 col_lens[0] = MAT_FILE_CLASSID; 582 col_lens[1] = A->rmap->n; 583 col_lens[2] = A->cmap->n; 584 col_lens[3] = a->nz; 585 586 /* store lengths of each row and write (including header) to file */ 587 for (i=0; i<A->rmap->n; i++) { 588 col_lens[4+i] = a->i[i+1] - a->i[i]; 589 } 590 ierr = PetscBinaryWrite(fd,col_lens,4+A->rmap->n,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 591 ierr = PetscFree(col_lens);CHKERRQ(ierr); 592 593 /* store column indices (zero start index) */ 594 ierr = PetscBinaryWrite(fd,a->j,a->nz,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 595 596 /* store nonzero values */ 597 ierr = PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr); 598 599 ierr = PetscViewerBinaryGetInfoPointer(viewer,&file);CHKERRQ(ierr); 600 if (file) { 601 fprintf(file,"-matload_block_size %d\n",(int)PetscAbs(A->rmap->bs)); 602 } 603 PetscFunctionReturn(0); 604 } 605 606 static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer) 607 { 608 PetscErrorCode ierr; 609 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 610 PetscInt i,k,m=A->rmap->N; 611 612 PetscFunctionBegin; 613 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 614 for (i=0; i<m; i++) { 615 ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr); 616 for (k=a->i[i]; k<a->i[i+1]; k++) { 617 ierr = PetscViewerASCIIPrintf(viewer," (%D) ",a->j[k]);CHKERRQ(ierr); 618 } 619 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 620 } 621 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 622 PetscFunctionReturn(0); 623 } 624 625 extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer); 626 627 PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer) 628 { 629 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 630 PetscErrorCode ierr; 631 PetscInt i,j,m = A->rmap->n; 632 const char *name; 633 PetscViewerFormat format; 634 635 PetscFunctionBegin; 636 if (A->structure_only) { 637 ierr = MatView_SeqAIJ_ASCII_structonly(A,viewer);CHKERRQ(ierr); 638 PetscFunctionReturn(0); 639 } 640 641 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 642 if (format == PETSC_VIEWER_ASCII_MATLAB) { 643 PetscInt nofinalvalue = 0; 644 if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) { 645 /* Need a dummy value to ensure the dimension of the matrix. */ 646 nofinalvalue = 1; 647 } 648 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 649 ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr); 650 ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr); 651 #if defined(PETSC_USE_COMPLEX) 652 ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,4);\n",a->nz+nofinalvalue);CHKERRQ(ierr); 653 #else 654 ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr); 655 #endif 656 ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr); 657 658 for (i=0; i<m; i++) { 659 for (j=a->i[i]; j<a->i[i+1]; j++) { 660 #if defined(PETSC_USE_COMPLEX) 661 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %18.16e %18.16e\n",i+1,a->j[j]+1,(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 662 #else 663 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]);CHKERRQ(ierr); 664 #endif 665 } 666 } 667 if (nofinalvalue) { 668 #if defined(PETSC_USE_COMPLEX) 669 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %18.16e %18.16e\n",m,A->cmap->n,0.,0.);CHKERRQ(ierr); 670 #else 671 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr); 672 #endif 673 } 674 ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr); 675 ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr); 676 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 677 } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) { 678 PetscFunctionReturn(0); 679 } else if (format == PETSC_VIEWER_ASCII_COMMON) { 680 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 681 for (i=0; i<m; i++) { 682 ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr); 683 for (j=a->i[i]; j<a->i[i+1]; j++) { 684 #if defined(PETSC_USE_COMPLEX) 685 if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) { 686 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 687 } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) { 688 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 689 } else if (PetscRealPart(a->a[j]) != 0.0) { 690 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr); 691 } 692 #else 693 if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);} 694 #endif 695 } 696 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 697 } 698 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 699 } else if (format == PETSC_VIEWER_ASCII_SYMMODU) { 700 PetscInt nzd=0,fshift=1,*sptr; 701 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 702 ierr = PetscMalloc1(m+1,&sptr);CHKERRQ(ierr); 703 for (i=0; i<m; i++) { 704 sptr[i] = nzd+1; 705 for (j=a->i[i]; j<a->i[i+1]; j++) { 706 if (a->j[j] >= i) { 707 #if defined(PETSC_USE_COMPLEX) 708 if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++; 709 #else 710 if (a->a[j] != 0.0) nzd++; 711 #endif 712 } 713 } 714 } 715 sptr[m] = nzd+1; 716 ierr = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr); 717 for (i=0; i<m+1; i+=6) { 718 if (i+4<m) { 719 ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4],sptr[i+5]);CHKERRQ(ierr); 720 } else if (i+3<m) { 721 ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4]);CHKERRQ(ierr); 722 } else if (i+2<m) { 723 ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr); 724 } else if (i+1<m) { 725 ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr); 726 } else if (i<m) { 727 ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr); 728 } else { 729 ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr); 730 } 731 } 732 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 733 ierr = PetscFree(sptr);CHKERRQ(ierr); 734 for (i=0; i<m; i++) { 735 for (j=a->i[i]; j<a->i[i+1]; j++) { 736 if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);} 737 } 738 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 739 } 740 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 741 for (i=0; i<m; i++) { 742 for (j=a->i[i]; j<a->i[i+1]; j++) { 743 if (a->j[j] >= i) { 744 #if defined(PETSC_USE_COMPLEX) 745 if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) { 746 ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 747 } 748 #else 749 if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]);CHKERRQ(ierr);} 750 #endif 751 } 752 } 753 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 754 } 755 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 756 } else if (format == PETSC_VIEWER_ASCII_DENSE) { 757 PetscInt cnt = 0,jcnt; 758 PetscScalar value; 759 #if defined(PETSC_USE_COMPLEX) 760 PetscBool realonly = PETSC_TRUE; 761 762 for (i=0; i<a->i[m]; i++) { 763 if (PetscImaginaryPart(a->a[i]) != 0.0) { 764 realonly = PETSC_FALSE; 765 break; 766 } 767 } 768 #endif 769 770 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 771 for (i=0; i<m; i++) { 772 jcnt = 0; 773 for (j=0; j<A->cmap->n; j++) { 774 if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) { 775 value = a->a[cnt++]; 776 jcnt++; 777 } else { 778 value = 0.0; 779 } 780 #if defined(PETSC_USE_COMPLEX) 781 if (realonly) { 782 ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value));CHKERRQ(ierr); 783 } else { 784 ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value));CHKERRQ(ierr); 785 } 786 #else 787 ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value);CHKERRQ(ierr); 788 #endif 789 } 790 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 791 } 792 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 793 } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) { 794 PetscInt fshift=1; 795 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 796 #if defined(PETSC_USE_COMPLEX) 797 ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n");CHKERRQ(ierr); 798 #else 799 ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n");CHKERRQ(ierr); 800 #endif 801 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr); 802 for (i=0; i<m; i++) { 803 for (j=a->i[i]; j<a->i[i+1]; j++) { 804 #if defined(PETSC_USE_COMPLEX) 805 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g %g\n", i+fshift,a->j[j]+fshift,(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 806 #else 807 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]);CHKERRQ(ierr); 808 #endif 809 } 810 } 811 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 812 } else { 813 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 814 if (A->factortype) { 815 for (i=0; i<m; i++) { 816 ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr); 817 /* L part */ 818 for (j=a->i[i]; j<a->i[i+1]; j++) { 819 #if defined(PETSC_USE_COMPLEX) 820 if (PetscImaginaryPart(a->a[j]) > 0.0) { 821 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 822 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 823 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr); 824 } else { 825 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr); 826 } 827 #else 828 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr); 829 #endif 830 } 831 /* diagonal */ 832 j = a->diag[i]; 833 #if defined(PETSC_USE_COMPLEX) 834 if (PetscImaginaryPart(a->a[j]) > 0.0) { 835 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)PetscImaginaryPart(1.0/a->a[j]));CHKERRQ(ierr); 836 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 837 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)(-PetscImaginaryPart(1.0/a->a[j])));CHKERRQ(ierr); 838 } else { 839 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j]));CHKERRQ(ierr); 840 } 841 #else 842 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)(1.0/a->a[j]));CHKERRQ(ierr); 843 #endif 844 845 /* U part */ 846 for (j=a->diag[i+1]+1; j<a->diag[i]; j++) { 847 #if defined(PETSC_USE_COMPLEX) 848 if (PetscImaginaryPart(a->a[j]) > 0.0) { 849 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 850 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 851 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr); 852 } else { 853 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr); 854 } 855 #else 856 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr); 857 #endif 858 } 859 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 860 } 861 } else { 862 for (i=0; i<m; i++) { 863 ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr); 864 for (j=a->i[i]; j<a->i[i+1]; j++) { 865 #if defined(PETSC_USE_COMPLEX) 866 if (PetscImaginaryPart(a->a[j]) > 0.0) { 867 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 868 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 869 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 870 } else { 871 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr); 872 } 873 #else 874 ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr); 875 #endif 876 } 877 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 878 } 879 } 880 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 881 } 882 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 883 PetscFunctionReturn(0); 884 } 885 886 #include <petscdraw.h> 887 PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa) 888 { 889 Mat A = (Mat) Aa; 890 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 891 PetscErrorCode ierr; 892 PetscInt i,j,m = A->rmap->n; 893 int color; 894 PetscReal xl,yl,xr,yr,x_l,x_r,y_l,y_r; 895 PetscViewer viewer; 896 PetscViewerFormat format; 897 898 PetscFunctionBegin; 899 ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr); 900 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 901 ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 902 903 /* loop over matrix elements drawing boxes */ 904 905 if (format != PETSC_VIEWER_DRAW_CONTOUR) { 906 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 907 /* Blue for negative, Cyan for zero and Red for positive */ 908 color = PETSC_DRAW_BLUE; 909 for (i=0; i<m; i++) { 910 y_l = m - i - 1.0; y_r = y_l + 1.0; 911 for (j=a->i[i]; j<a->i[i+1]; j++) { 912 x_l = a->j[j]; x_r = x_l + 1.0; 913 if (PetscRealPart(a->a[j]) >= 0.) continue; 914 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 915 } 916 } 917 color = PETSC_DRAW_CYAN; 918 for (i=0; i<m; i++) { 919 y_l = m - i - 1.0; y_r = y_l + 1.0; 920 for (j=a->i[i]; j<a->i[i+1]; j++) { 921 x_l = a->j[j]; x_r = x_l + 1.0; 922 if (a->a[j] != 0.) continue; 923 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 924 } 925 } 926 color = PETSC_DRAW_RED; 927 for (i=0; i<m; i++) { 928 y_l = m - i - 1.0; y_r = y_l + 1.0; 929 for (j=a->i[i]; j<a->i[i+1]; j++) { 930 x_l = a->j[j]; x_r = x_l + 1.0; 931 if (PetscRealPart(a->a[j]) <= 0.) continue; 932 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 933 } 934 } 935 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 936 } else { 937 /* use contour shading to indicate magnitude of values */ 938 /* first determine max of all nonzero values */ 939 PetscReal minv = 0.0, maxv = 0.0; 940 PetscInt nz = a->nz, count = 0; 941 PetscDraw popup; 942 943 for (i=0; i<nz; i++) { 944 if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]); 945 } 946 if (minv >= maxv) maxv = minv + PETSC_SMALL; 947 ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr); 948 ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr); 949 950 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 951 for (i=0; i<m; i++) { 952 y_l = m - i - 1.0; 953 y_r = y_l + 1.0; 954 for (j=a->i[i]; j<a->i[i+1]; j++) { 955 x_l = a->j[j]; 956 x_r = x_l + 1.0; 957 color = PetscDrawRealToColor(PetscAbsScalar(a->a[count]),minv,maxv); 958 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 959 count++; 960 } 961 } 962 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 963 } 964 PetscFunctionReturn(0); 965 } 966 967 #include <petscdraw.h> 968 PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer) 969 { 970 PetscErrorCode ierr; 971 PetscDraw draw; 972 PetscReal xr,yr,xl,yl,h,w; 973 PetscBool isnull; 974 975 PetscFunctionBegin; 976 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 977 ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); 978 if (isnull) PetscFunctionReturn(0); 979 980 xr = A->cmap->n; yr = A->rmap->n; h = yr/10.0; w = xr/10.0; 981 xr += w; yr += h; xl = -w; yl = -h; 982 ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr); 983 ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr); 984 ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr); 985 ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr); 986 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 987 PetscFunctionReturn(0); 988 } 989 990 PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer) 991 { 992 PetscErrorCode ierr; 993 PetscBool iascii,isbinary,isdraw; 994 995 PetscFunctionBegin; 996 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 997 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 998 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 999 if (iascii) { 1000 ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr); 1001 } else if (isbinary) { 1002 ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr); 1003 } else if (isdraw) { 1004 ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr); 1005 } 1006 ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr); 1007 PetscFunctionReturn(0); 1008 } 1009 1010 PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode) 1011 { 1012 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1013 PetscErrorCode ierr; 1014 PetscInt fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax; 1015 PetscInt m = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0; 1016 MatScalar *aa = a->a,*ap; 1017 PetscReal ratio = 0.6; 1018 1019 PetscFunctionBegin; 1020 if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 1021 ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr); 1022 if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) PetscFunctionReturn(0); 1023 1024 if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 1025 for (i=1; i<m; i++) { 1026 /* move each row back by the amount of empty slots (fshift) before it*/ 1027 fshift += imax[i-1] - ailen[i-1]; 1028 rmax = PetscMax(rmax,ailen[i]); 1029 if (fshift) { 1030 ip = aj + ai[i]; 1031 ap = aa + ai[i]; 1032 N = ailen[i]; 1033 ierr = PetscArraymove(ip-fshift,ip,N);CHKERRQ(ierr); 1034 if (!A->structure_only) { 1035 ierr = PetscArraymove(ap-fshift,ap,N);CHKERRQ(ierr); 1036 } 1037 } 1038 ai[i] = ai[i-1] + ailen[i-1]; 1039 } 1040 if (m) { 1041 fshift += imax[m-1] - ailen[m-1]; 1042 ai[m] = ai[m-1] + ailen[m-1]; 1043 } 1044 1045 /* reset ilen and imax for each row */ 1046 a->nonzerorowcnt = 0; 1047 if (A->structure_only) { 1048 ierr = PetscFree(a->imax);CHKERRQ(ierr); 1049 ierr = PetscFree(a->ilen);CHKERRQ(ierr); 1050 } else { /* !A->structure_only */ 1051 for (i=0; i<m; i++) { 1052 ailen[i] = imax[i] = ai[i+1] - ai[i]; 1053 a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0); 1054 } 1055 } 1056 a->nz = ai[m]; 1057 if (fshift && a->nounused == -1) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Unused space detected in matrix: %D X %D, %D unneeded", m, A->cmap->n, fshift); 1058 1059 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 1060 ierr = PetscInfo4(A,"Matrix size: %D X %D; storage space: %D unneeded,%D used\n",m,A->cmap->n,fshift,a->nz);CHKERRQ(ierr); 1061 ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr); 1062 ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr); 1063 1064 A->info.mallocs += a->reallocs; 1065 a->reallocs = 0; 1066 A->info.nz_unneeded = (PetscReal)fshift; 1067 a->rmax = rmax; 1068 1069 if (!A->structure_only) { 1070 ierr = MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr); 1071 } 1072 ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr); 1073 PetscFunctionReturn(0); 1074 } 1075 1076 PetscErrorCode MatRealPart_SeqAIJ(Mat A) 1077 { 1078 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1079 PetscInt i,nz = a->nz; 1080 MatScalar *aa = a->a; 1081 PetscErrorCode ierr; 1082 1083 PetscFunctionBegin; 1084 for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]); 1085 ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr); 1086 PetscFunctionReturn(0); 1087 } 1088 1089 PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A) 1090 { 1091 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1092 PetscInt i,nz = a->nz; 1093 MatScalar *aa = a->a; 1094 PetscErrorCode ierr; 1095 1096 PetscFunctionBegin; 1097 for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]); 1098 ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr); 1099 PetscFunctionReturn(0); 1100 } 1101 1102 PetscErrorCode MatZeroEntries_SeqAIJ(Mat A) 1103 { 1104 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1105 PetscErrorCode ierr; 1106 1107 PetscFunctionBegin; 1108 ierr = PetscArrayzero(a->a,a->i[A->rmap->n]);CHKERRQ(ierr); 1109 ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr); 1110 PetscFunctionReturn(0); 1111 } 1112 1113 PetscErrorCode MatDestroy_SeqAIJ(Mat A) 1114 { 1115 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1116 PetscErrorCode ierr; 1117 1118 PetscFunctionBegin; 1119 #if defined(PETSC_USE_LOG) 1120 PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz); 1121 #endif 1122 ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr); 1123 ierr = ISDestroy(&a->row);CHKERRQ(ierr); 1124 ierr = ISDestroy(&a->col);CHKERRQ(ierr); 1125 ierr = PetscFree(a->diag);CHKERRQ(ierr); 1126 ierr = PetscFree(a->ibdiag);CHKERRQ(ierr); 1127 ierr = PetscFree(a->imax);CHKERRQ(ierr); 1128 ierr = PetscFree(a->ilen);CHKERRQ(ierr); 1129 ierr = PetscFree(a->ipre);CHKERRQ(ierr); 1130 ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr); 1131 ierr = PetscFree(a->solve_work);CHKERRQ(ierr); 1132 ierr = ISDestroy(&a->icol);CHKERRQ(ierr); 1133 ierr = PetscFree(a->saved_values);CHKERRQ(ierr); 1134 ierr = ISColoringDestroy(&a->coloring);CHKERRQ(ierr); 1135 ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr); 1136 ierr = PetscFree(a->matmult_abdense);CHKERRQ(ierr); 1137 1138 ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr); 1139 ierr = PetscFree(A->data);CHKERRQ(ierr); 1140 1141 ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 1142 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr); 1143 ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr); 1144 ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr); 1145 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr); 1146 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr); 1147 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr); 1148 #if defined(PETSC_HAVE_ELEMENTAL) 1149 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr); 1150 #endif 1151 #if defined(PETSC_HAVE_HYPRE) 1152 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr); 1153 ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMatMult_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr); 1154 #endif 1155 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr); 1156 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr); 1157 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr); 1158 ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr); 1159 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr); 1160 ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr); 1161 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr); 1162 ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr); 1163 ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_is_seqaij_C",NULL);CHKERRQ(ierr); 1164 PetscFunctionReturn(0); 1165 } 1166 1167 PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg) 1168 { 1169 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1170 PetscErrorCode ierr; 1171 1172 PetscFunctionBegin; 1173 switch (op) { 1174 case MAT_ROW_ORIENTED: 1175 a->roworiented = flg; 1176 break; 1177 case MAT_KEEP_NONZERO_PATTERN: 1178 a->keepnonzeropattern = flg; 1179 break; 1180 case MAT_NEW_NONZERO_LOCATIONS: 1181 a->nonew = (flg ? 0 : 1); 1182 break; 1183 case MAT_NEW_NONZERO_LOCATION_ERR: 1184 a->nonew = (flg ? -1 : 0); 1185 break; 1186 case MAT_NEW_NONZERO_ALLOCATION_ERR: 1187 a->nonew = (flg ? -2 : 0); 1188 break; 1189 case MAT_UNUSED_NONZERO_LOCATION_ERR: 1190 a->nounused = (flg ? -1 : 0); 1191 break; 1192 case MAT_IGNORE_ZERO_ENTRIES: 1193 a->ignorezeroentries = flg; 1194 break; 1195 case MAT_SPD: 1196 case MAT_SYMMETRIC: 1197 case MAT_STRUCTURALLY_SYMMETRIC: 1198 case MAT_HERMITIAN: 1199 case MAT_SYMMETRY_ETERNAL: 1200 case MAT_STRUCTURE_ONLY: 1201 /* These options are handled directly by MatSetOption() */ 1202 break; 1203 case MAT_NEW_DIAGONALS: 1204 case MAT_IGNORE_OFF_PROC_ENTRIES: 1205 case MAT_USE_HASH_TABLE: 1206 ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr); 1207 break; 1208 case MAT_USE_INODES: 1209 /* Not an error because MatSetOption_SeqAIJ_Inode handles this one */ 1210 break; 1211 case MAT_SUBMAT_SINGLEIS: 1212 A->submat_singleis = flg; 1213 break; 1214 case MAT_SORTED_FULL: 1215 if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 1216 else A->ops->setvalues = MatSetValues_SeqAIJ; 1217 break; 1218 default: 1219 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op); 1220 } 1221 ierr = MatSetOption_SeqAIJ_Inode(A,op,flg);CHKERRQ(ierr); 1222 PetscFunctionReturn(0); 1223 } 1224 1225 PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v) 1226 { 1227 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1228 PetscErrorCode ierr; 1229 PetscInt i,j,n,*ai=a->i,*aj=a->j; 1230 PetscScalar *aa=a->a,*x; 1231 1232 PetscFunctionBegin; 1233 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 1234 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 1235 1236 if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) { 1237 PetscInt *diag=a->diag; 1238 ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr); 1239 for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]]; 1240 ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr); 1241 PetscFunctionReturn(0); 1242 } 1243 1244 ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr); 1245 for (i=0; i<n; i++) { 1246 x[i] = 0.0; 1247 for (j=ai[i]; j<ai[i+1]; j++) { 1248 if (aj[j] == i) { 1249 x[i] = aa[j]; 1250 break; 1251 } 1252 } 1253 } 1254 ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr); 1255 PetscFunctionReturn(0); 1256 } 1257 1258 #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 1259 PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy) 1260 { 1261 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1262 PetscScalar *y; 1263 const PetscScalar *x; 1264 PetscErrorCode ierr; 1265 PetscInt m = A->rmap->n; 1266 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 1267 const MatScalar *v; 1268 PetscScalar alpha; 1269 PetscInt n,i,j; 1270 const PetscInt *idx,*ii,*ridx=NULL; 1271 Mat_CompressedRow cprow = a->compressedrow; 1272 PetscBool usecprow = cprow.use; 1273 #endif 1274 1275 PetscFunctionBegin; 1276 if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);} 1277 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 1278 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 1279 1280 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 1281 fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y); 1282 #else 1283 if (usecprow) { 1284 m = cprow.nrows; 1285 ii = cprow.i; 1286 ridx = cprow.rindex; 1287 } else { 1288 ii = a->i; 1289 } 1290 for (i=0; i<m; i++) { 1291 idx = a->j + ii[i]; 1292 v = a->a + ii[i]; 1293 n = ii[i+1] - ii[i]; 1294 if (usecprow) { 1295 alpha = x[ridx[i]]; 1296 } else { 1297 alpha = x[i]; 1298 } 1299 for (j=0; j<n; j++) y[idx[j]] += alpha*v[j]; 1300 } 1301 #endif 1302 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1303 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1304 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 1305 PetscFunctionReturn(0); 1306 } 1307 1308 PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy) 1309 { 1310 PetscErrorCode ierr; 1311 1312 PetscFunctionBegin; 1313 ierr = VecSet(yy,0.0);CHKERRQ(ierr); 1314 ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr); 1315 PetscFunctionReturn(0); 1316 } 1317 1318 #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 1319 1320 PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy) 1321 { 1322 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1323 PetscScalar *y; 1324 const PetscScalar *x; 1325 const MatScalar *aa; 1326 PetscErrorCode ierr; 1327 PetscInt m=A->rmap->n; 1328 const PetscInt *aj,*ii,*ridx=NULL; 1329 PetscInt n,i; 1330 PetscScalar sum; 1331 PetscBool usecprow=a->compressedrow.use; 1332 1333 #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 1334 #pragma disjoint(*x,*y,*aa) 1335 #endif 1336 1337 PetscFunctionBegin; 1338 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 1339 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 1340 ii = a->i; 1341 if (usecprow) { /* use compressed row format */ 1342 ierr = PetscArrayzero(y,m);CHKERRQ(ierr); 1343 m = a->compressedrow.nrows; 1344 ii = a->compressedrow.i; 1345 ridx = a->compressedrow.rindex; 1346 for (i=0; i<m; i++) { 1347 n = ii[i+1] - ii[i]; 1348 aj = a->j + ii[i]; 1349 aa = a->a + ii[i]; 1350 sum = 0.0; 1351 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1352 /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 1353 y[*ridx++] = sum; 1354 } 1355 } else { /* do not use compressed row format */ 1356 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ) 1357 aj = a->j; 1358 aa = a->a; 1359 fortranmultaij_(&m,x,ii,aj,aa,y); 1360 #else 1361 for (i=0; i<m; i++) { 1362 n = ii[i+1] - ii[i]; 1363 aj = a->j + ii[i]; 1364 aa = a->a + ii[i]; 1365 sum = 0.0; 1366 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1367 y[i] = sum; 1368 } 1369 #endif 1370 } 1371 ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr); 1372 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1373 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 1374 PetscFunctionReturn(0); 1375 } 1376 1377 PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy) 1378 { 1379 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1380 PetscScalar *y; 1381 const PetscScalar *x; 1382 const MatScalar *aa; 1383 PetscErrorCode ierr; 1384 PetscInt m=A->rmap->n; 1385 const PetscInt *aj,*ii,*ridx=NULL; 1386 PetscInt n,i,nonzerorow=0; 1387 PetscScalar sum; 1388 PetscBool usecprow=a->compressedrow.use; 1389 1390 #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 1391 #pragma disjoint(*x,*y,*aa) 1392 #endif 1393 1394 PetscFunctionBegin; 1395 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 1396 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 1397 if (usecprow) { /* use compressed row format */ 1398 m = a->compressedrow.nrows; 1399 ii = a->compressedrow.i; 1400 ridx = a->compressedrow.rindex; 1401 for (i=0; i<m; i++) { 1402 n = ii[i+1] - ii[i]; 1403 aj = a->j + ii[i]; 1404 aa = a->a + ii[i]; 1405 sum = 0.0; 1406 nonzerorow += (n>0); 1407 PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1408 /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 1409 y[*ridx++] = sum; 1410 } 1411 } else { /* do not use compressed row format */ 1412 ii = a->i; 1413 for (i=0; i<m; i++) { 1414 n = ii[i+1] - ii[i]; 1415 aj = a->j + ii[i]; 1416 aa = a->a + ii[i]; 1417 sum = 0.0; 1418 nonzerorow += (n>0); 1419 PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1420 y[i] = sum; 1421 } 1422 } 1423 ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr); 1424 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1425 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 1426 PetscFunctionReturn(0); 1427 } 1428 1429 PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1430 { 1431 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1432 PetscScalar *y,*z; 1433 const PetscScalar *x; 1434 const MatScalar *aa; 1435 PetscErrorCode ierr; 1436 PetscInt m = A->rmap->n,*aj,*ii; 1437 PetscInt n,i,*ridx=NULL; 1438 PetscScalar sum; 1439 PetscBool usecprow=a->compressedrow.use; 1440 1441 PetscFunctionBegin; 1442 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 1443 ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr); 1444 if (usecprow) { /* use compressed row format */ 1445 if (zz != yy) { 1446 ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr); 1447 } 1448 m = a->compressedrow.nrows; 1449 ii = a->compressedrow.i; 1450 ridx = a->compressedrow.rindex; 1451 for (i=0; i<m; i++) { 1452 n = ii[i+1] - ii[i]; 1453 aj = a->j + ii[i]; 1454 aa = a->a + ii[i]; 1455 sum = y[*ridx]; 1456 PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1457 z[*ridx++] = sum; 1458 } 1459 } else { /* do not use compressed row format */ 1460 ii = a->i; 1461 for (i=0; i<m; i++) { 1462 n = ii[i+1] - ii[i]; 1463 aj = a->j + ii[i]; 1464 aa = a->a + ii[i]; 1465 sum = y[i]; 1466 PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1467 z[i] = sum; 1468 } 1469 } 1470 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1471 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1472 ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr); 1473 PetscFunctionReturn(0); 1474 } 1475 1476 #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h> 1477 PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1478 { 1479 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1480 PetscScalar *y,*z; 1481 const PetscScalar *x; 1482 const MatScalar *aa; 1483 PetscErrorCode ierr; 1484 const PetscInt *aj,*ii,*ridx=NULL; 1485 PetscInt m = A->rmap->n,n,i; 1486 PetscScalar sum; 1487 PetscBool usecprow=a->compressedrow.use; 1488 1489 PetscFunctionBegin; 1490 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 1491 ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr); 1492 if (usecprow) { /* use compressed row format */ 1493 if (zz != yy) { 1494 ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr); 1495 } 1496 m = a->compressedrow.nrows; 1497 ii = a->compressedrow.i; 1498 ridx = a->compressedrow.rindex; 1499 for (i=0; i<m; i++) { 1500 n = ii[i+1] - ii[i]; 1501 aj = a->j + ii[i]; 1502 aa = a->a + ii[i]; 1503 sum = y[*ridx]; 1504 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1505 z[*ridx++] = sum; 1506 } 1507 } else { /* do not use compressed row format */ 1508 ii = a->i; 1509 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ) 1510 aj = a->j; 1511 aa = a->a; 1512 fortranmultaddaij_(&m,x,ii,aj,aa,y,z); 1513 #else 1514 for (i=0; i<m; i++) { 1515 n = ii[i+1] - ii[i]; 1516 aj = a->j + ii[i]; 1517 aa = a->a + ii[i]; 1518 sum = y[i]; 1519 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1520 z[i] = sum; 1521 } 1522 #endif 1523 } 1524 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1525 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1526 ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr); 1527 PetscFunctionReturn(0); 1528 } 1529 1530 /* 1531 Adds diagonal pointers to sparse matrix structure. 1532 */ 1533 PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A) 1534 { 1535 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1536 PetscErrorCode ierr; 1537 PetscInt i,j,m = A->rmap->n; 1538 1539 PetscFunctionBegin; 1540 if (!a->diag) { 1541 ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr); 1542 ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr); 1543 } 1544 for (i=0; i<A->rmap->n; i++) { 1545 a->diag[i] = a->i[i+1]; 1546 for (j=a->i[i]; j<a->i[i+1]; j++) { 1547 if (a->j[j] == i) { 1548 a->diag[i] = j; 1549 break; 1550 } 1551 } 1552 } 1553 PetscFunctionReturn(0); 1554 } 1555 1556 PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v) 1557 { 1558 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1559 const PetscInt *diag = (const PetscInt*)a->diag; 1560 const PetscInt *ii = (const PetscInt*) a->i; 1561 PetscInt i,*mdiag = NULL; 1562 PetscErrorCode ierr; 1563 PetscInt cnt = 0; /* how many diagonals are missing */ 1564 1565 PetscFunctionBegin; 1566 if (!A->preallocated || !a->nz) { 1567 ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr); 1568 ierr = MatShift_Basic(A,v);CHKERRQ(ierr); 1569 PetscFunctionReturn(0); 1570 } 1571 1572 if (a->diagonaldense) { 1573 cnt = 0; 1574 } else { 1575 ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr); 1576 for (i=0; i<A->rmap->n; i++) { 1577 if (diag[i] >= ii[i+1]) { 1578 cnt++; 1579 mdiag[i] = 1; 1580 } 1581 } 1582 } 1583 if (!cnt) { 1584 ierr = MatShift_Basic(A,v);CHKERRQ(ierr); 1585 } else { 1586 PetscScalar *olda = a->a; /* preserve pointers to current matrix nonzeros structure and values */ 1587 PetscInt *oldj = a->j, *oldi = a->i; 1588 PetscBool singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij; 1589 1590 a->a = NULL; 1591 a->j = NULL; 1592 a->i = NULL; 1593 /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */ 1594 for (i=0; i<A->rmap->n; i++) { 1595 a->imax[i] += mdiag[i]; 1596 a->imax[i] = PetscMin(a->imax[i],A->cmap->n); 1597 } 1598 ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr); 1599 1600 /* copy old values into new matrix data structure */ 1601 for (i=0; i<A->rmap->n; i++) { 1602 ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr); 1603 if (i < A->cmap->n) { 1604 ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr); 1605 } 1606 } 1607 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1608 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1609 if (singlemalloc) { 1610 ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr); 1611 } else { 1612 if (free_a) {ierr = PetscFree(olda);CHKERRQ(ierr);} 1613 if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);} 1614 if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);} 1615 } 1616 } 1617 ierr = PetscFree(mdiag);CHKERRQ(ierr); 1618 a->diagonaldense = PETSC_TRUE; 1619 PetscFunctionReturn(0); 1620 } 1621 1622 /* 1623 Checks for missing diagonals 1624 */ 1625 PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool *missing,PetscInt *d) 1626 { 1627 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1628 PetscInt *diag,*ii = a->i,i; 1629 PetscErrorCode ierr; 1630 1631 PetscFunctionBegin; 1632 *missing = PETSC_FALSE; 1633 if (A->rmap->n > 0 && !ii) { 1634 *missing = PETSC_TRUE; 1635 if (d) *d = 0; 1636 ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr); 1637 } else { 1638 PetscInt n; 1639 n = PetscMin(A->rmap->n, A->cmap->n); 1640 diag = a->diag; 1641 for (i=0; i<n; i++) { 1642 if (diag[i] >= ii[i+1]) { 1643 *missing = PETSC_TRUE; 1644 if (d) *d = i; 1645 ierr = PetscInfo1(A,"Matrix is missing diagonal number %D\n",i);CHKERRQ(ierr); 1646 break; 1647 } 1648 } 1649 } 1650 PetscFunctionReturn(0); 1651 } 1652 1653 #include <petscblaslapack.h> 1654 #include <petsc/private/kernels/blockinvert.h> 1655 1656 /* 1657 Note that values is allocated externally by the PC and then passed into this routine 1658 */ 1659 PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag) 1660 { 1661 PetscErrorCode ierr; 1662 PetscInt n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots; 1663 PetscBool allowzeropivot,zeropivotdetected=PETSC_FALSE; 1664 const PetscReal shift = 0.0; 1665 PetscInt ipvt[5]; 1666 PetscScalar work[25],*v_work; 1667 1668 PetscFunctionBegin; 1669 allowzeropivot = PetscNot(A->erroriffailure); 1670 for (i=0; i<nblocks; i++) ncnt += bsizes[i]; 1671 if (ncnt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %D doesn't match number matrix rows %D",ncnt,n); 1672 for (i=0; i<nblocks; i++) { 1673 bsizemax = PetscMax(bsizemax,bsizes[i]); 1674 } 1675 ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr); 1676 if (bsizemax > 7) { 1677 ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr); 1678 } 1679 ncnt = 0; 1680 for (i=0; i<nblocks; i++) { 1681 for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j; 1682 ierr = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr); 1683 switch (bsizes[i]) { 1684 case 1: 1685 *diag = 1.0/(*diag); 1686 break; 1687 case 2: 1688 ierr = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 1689 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1690 ierr = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr); 1691 break; 1692 case 3: 1693 ierr = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 1694 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1695 ierr = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr); 1696 break; 1697 case 4: 1698 ierr = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 1699 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1700 ierr = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr); 1701 break; 1702 case 5: 1703 ierr = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 1704 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1705 ierr = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr); 1706 break; 1707 case 6: 1708 ierr = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 1709 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1710 ierr = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr); 1711 break; 1712 case 7: 1713 ierr = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 1714 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1715 ierr = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr); 1716 break; 1717 default: 1718 ierr = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 1719 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1720 ierr = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr); 1721 } 1722 ncnt += bsizes[i]; 1723 diag += bsizes[i]*bsizes[i]; 1724 } 1725 if (bsizemax > 7) { 1726 ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr); 1727 } 1728 ierr = PetscFree(indx);CHKERRQ(ierr); 1729 PetscFunctionReturn(0); 1730 } 1731 1732 /* 1733 Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways 1734 */ 1735 PetscErrorCode MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift) 1736 { 1737 Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 1738 PetscErrorCode ierr; 1739 PetscInt i,*diag,m = A->rmap->n; 1740 MatScalar *v = a->a; 1741 PetscScalar *idiag,*mdiag; 1742 1743 PetscFunctionBegin; 1744 if (a->idiagvalid) PetscFunctionReturn(0); 1745 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 1746 diag = a->diag; 1747 if (!a->idiag) { 1748 ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr); 1749 ierr = PetscLogObjectMemory((PetscObject)A, 3*m*sizeof(PetscScalar));CHKERRQ(ierr); 1750 v = a->a; 1751 } 1752 mdiag = a->mdiag; 1753 idiag = a->idiag; 1754 1755 if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) { 1756 for (i=0; i<m; i++) { 1757 mdiag[i] = v[diag[i]]; 1758 if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */ 1759 if (PetscRealPart(fshift)) { 1760 ierr = PetscInfo1(A,"Zero diagonal on row %D\n",i);CHKERRQ(ierr); 1761 A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1762 A->factorerror_zeropivot_value = 0.0; 1763 A->factorerror_zeropivot_row = i; 1764 } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i); 1765 } 1766 idiag[i] = 1.0/v[diag[i]]; 1767 } 1768 ierr = PetscLogFlops(m);CHKERRQ(ierr); 1769 } else { 1770 for (i=0; i<m; i++) { 1771 mdiag[i] = v[diag[i]]; 1772 idiag[i] = omega/(fshift + v[diag[i]]); 1773 } 1774 ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr); 1775 } 1776 a->idiagvalid = PETSC_TRUE; 1777 PetscFunctionReturn(0); 1778 } 1779 1780 #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h> 1781 PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 1782 { 1783 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1784 PetscScalar *x,d,sum,*t,scale; 1785 const MatScalar *v,*idiag=0,*mdiag; 1786 const PetscScalar *b, *bs,*xb, *ts; 1787 PetscErrorCode ierr; 1788 PetscInt n,m = A->rmap->n,i; 1789 const PetscInt *idx,*diag; 1790 1791 PetscFunctionBegin; 1792 its = its*lits; 1793 1794 if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */ 1795 if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);} 1796 a->fshift = fshift; 1797 a->omega = omega; 1798 1799 diag = a->diag; 1800 t = a->ssor_work; 1801 idiag = a->idiag; 1802 mdiag = a->mdiag; 1803 1804 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 1805 ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr); 1806 /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */ 1807 if (flag == SOR_APPLY_UPPER) { 1808 /* apply (U + D/omega) to the vector */ 1809 bs = b; 1810 for (i=0; i<m; i++) { 1811 d = fshift + mdiag[i]; 1812 n = a->i[i+1] - diag[i] - 1; 1813 idx = a->j + diag[i] + 1; 1814 v = a->a + diag[i] + 1; 1815 sum = b[i]*d/omega; 1816 PetscSparseDensePlusDot(sum,bs,v,idx,n); 1817 x[i] = sum; 1818 } 1819 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1820 ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr); 1821 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 1822 PetscFunctionReturn(0); 1823 } 1824 1825 if (flag == SOR_APPLY_LOWER) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented"); 1826 else if (flag & SOR_EISENSTAT) { 1827 /* Let A = L + U + D; where L is lower trianglar, 1828 U is upper triangular, E = D/omega; This routine applies 1829 1830 (L + E)^{-1} A (U + E)^{-1} 1831 1832 to a vector efficiently using Eisenstat's trick. 1833 */ 1834 scale = (2.0/omega) - 1.0; 1835 1836 /* x = (E + U)^{-1} b */ 1837 for (i=m-1; i>=0; i--) { 1838 n = a->i[i+1] - diag[i] - 1; 1839 idx = a->j + diag[i] + 1; 1840 v = a->a + diag[i] + 1; 1841 sum = b[i]; 1842 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1843 x[i] = sum*idiag[i]; 1844 } 1845 1846 /* t = b - (2*E - D)x */ 1847 v = a->a; 1848 for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i]; 1849 1850 /* t = (E + L)^{-1}t */ 1851 ts = t; 1852 diag = a->diag; 1853 for (i=0; i<m; i++) { 1854 n = diag[i] - a->i[i]; 1855 idx = a->j + a->i[i]; 1856 v = a->a + a->i[i]; 1857 sum = t[i]; 1858 PetscSparseDenseMinusDot(sum,ts,v,idx,n); 1859 t[i] = sum*idiag[i]; 1860 /* x = x + t */ 1861 x[i] += t[i]; 1862 } 1863 1864 ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr); 1865 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1866 ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr); 1867 PetscFunctionReturn(0); 1868 } 1869 if (flag & SOR_ZERO_INITIAL_GUESS) { 1870 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 1871 for (i=0; i<m; i++) { 1872 n = diag[i] - a->i[i]; 1873 idx = a->j + a->i[i]; 1874 v = a->a + a->i[i]; 1875 sum = b[i]; 1876 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1877 t[i] = sum; 1878 x[i] = sum*idiag[i]; 1879 } 1880 xb = t; 1881 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 1882 } else xb = b; 1883 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 1884 for (i=m-1; i>=0; i--) { 1885 n = a->i[i+1] - diag[i] - 1; 1886 idx = a->j + diag[i] + 1; 1887 v = a->a + diag[i] + 1; 1888 sum = xb[i]; 1889 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1890 if (xb == b) { 1891 x[i] = sum*idiag[i]; 1892 } else { 1893 x[i] = (1-omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 1894 } 1895 } 1896 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */ 1897 } 1898 its--; 1899 } 1900 while (its--) { 1901 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 1902 for (i=0; i<m; i++) { 1903 /* lower */ 1904 n = diag[i] - a->i[i]; 1905 idx = a->j + a->i[i]; 1906 v = a->a + a->i[i]; 1907 sum = b[i]; 1908 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1909 t[i] = sum; /* save application of the lower-triangular part */ 1910 /* upper */ 1911 n = a->i[i+1] - diag[i] - 1; 1912 idx = a->j + diag[i] + 1; 1913 v = a->a + diag[i] + 1; 1914 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1915 x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 1916 } 1917 xb = t; 1918 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1919 } else xb = b; 1920 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 1921 for (i=m-1; i>=0; i--) { 1922 sum = xb[i]; 1923 if (xb == b) { 1924 /* whole matrix (no checkpointing available) */ 1925 n = a->i[i+1] - a->i[i]; 1926 idx = a->j + a->i[i]; 1927 v = a->a + a->i[i]; 1928 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1929 x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i]; 1930 } else { /* lower-triangular part has been saved, so only apply upper-triangular */ 1931 n = a->i[i+1] - diag[i] - 1; 1932 idx = a->j + diag[i] + 1; 1933 v = a->a + diag[i] + 1; 1934 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1935 x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 1936 } 1937 } 1938 if (xb == b) { 1939 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1940 } else { 1941 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */ 1942 } 1943 } 1944 } 1945 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1946 ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr); 1947 PetscFunctionReturn(0); 1948 } 1949 1950 1951 PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info) 1952 { 1953 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1954 1955 PetscFunctionBegin; 1956 info->block_size = 1.0; 1957 info->nz_allocated = (double)a->maxnz; 1958 info->nz_used = (double)a->nz; 1959 info->nz_unneeded = (double)(a->maxnz - a->nz); 1960 info->assemblies = (double)A->num_ass; 1961 info->mallocs = (double)A->info.mallocs; 1962 info->memory = ((PetscObject)A)->mem; 1963 if (A->factortype) { 1964 info->fill_ratio_given = A->info.fill_ratio_given; 1965 info->fill_ratio_needed = A->info.fill_ratio_needed; 1966 info->factor_mallocs = A->info.factor_mallocs; 1967 } else { 1968 info->fill_ratio_given = 0; 1969 info->fill_ratio_needed = 0; 1970 info->factor_mallocs = 0; 1971 } 1972 PetscFunctionReturn(0); 1973 } 1974 1975 PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1976 { 1977 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1978 PetscInt i,m = A->rmap->n - 1; 1979 PetscErrorCode ierr; 1980 const PetscScalar *xx; 1981 PetscScalar *bb; 1982 PetscInt d = 0; 1983 1984 PetscFunctionBegin; 1985 if (x && b) { 1986 ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 1987 ierr = VecGetArray(b,&bb);CHKERRQ(ierr); 1988 for (i=0; i<N; i++) { 1989 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 1990 if (rows[i] >= A->cmap->n) continue; 1991 bb[rows[i]] = diag*xx[rows[i]]; 1992 } 1993 ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 1994 ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr); 1995 } 1996 1997 if (a->keepnonzeropattern) { 1998 for (i=0; i<N; i++) { 1999 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 2000 ierr = PetscArrayzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr); 2001 } 2002 if (diag != 0.0) { 2003 for (i=0; i<N; i++) { 2004 d = rows[i]; 2005 if (rows[i] >= A->cmap->n) continue; 2006 if (a->diag[d] >= a->i[d+1]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in the zeroed row %D",d); 2007 } 2008 for (i=0; i<N; i++) { 2009 if (rows[i] >= A->cmap->n) continue; 2010 a->a[a->diag[rows[i]]] = diag; 2011 } 2012 } 2013 } else { 2014 if (diag != 0.0) { 2015 for (i=0; i<N; i++) { 2016 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 2017 if (a->ilen[rows[i]] > 0) { 2018 if (rows[i] >= A->cmap->n) { 2019 a->ilen[rows[i]] = 0; 2020 } else { 2021 a->ilen[rows[i]] = 1; 2022 a->a[a->i[rows[i]]] = diag; 2023 a->j[a->i[rows[i]]] = rows[i]; 2024 } 2025 } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */ 2026 ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr); 2027 } 2028 } 2029 } else { 2030 for (i=0; i<N; i++) { 2031 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 2032 a->ilen[rows[i]] = 0; 2033 } 2034 } 2035 A->nonzerostate++; 2036 } 2037 ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2038 PetscFunctionReturn(0); 2039 } 2040 2041 PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 2042 { 2043 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2044 PetscInt i,j,m = A->rmap->n - 1,d = 0; 2045 PetscErrorCode ierr; 2046 PetscBool missing,*zeroed,vecs = PETSC_FALSE; 2047 const PetscScalar *xx; 2048 PetscScalar *bb; 2049 2050 PetscFunctionBegin; 2051 if (x && b) { 2052 ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 2053 ierr = VecGetArray(b,&bb);CHKERRQ(ierr); 2054 vecs = PETSC_TRUE; 2055 } 2056 ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr); 2057 for (i=0; i<N; i++) { 2058 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 2059 ierr = PetscArrayzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr); 2060 2061 zeroed[rows[i]] = PETSC_TRUE; 2062 } 2063 for (i=0; i<A->rmap->n; i++) { 2064 if (!zeroed[i]) { 2065 for (j=a->i[i]; j<a->i[i+1]; j++) { 2066 if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) { 2067 if (vecs) bb[i] -= a->a[j]*xx[a->j[j]]; 2068 a->a[j] = 0.0; 2069 } 2070 } 2071 } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i]; 2072 } 2073 if (x && b) { 2074 ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 2075 ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr); 2076 } 2077 ierr = PetscFree(zeroed);CHKERRQ(ierr); 2078 if (diag != 0.0) { 2079 ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr); 2080 if (missing) { 2081 for (i=0; i<N; i++) { 2082 if (rows[i] >= A->cmap->N) continue; 2083 if (a->nonew && rows[i] >= d) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D (%D)",d,rows[i]); 2084 ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr); 2085 } 2086 } else { 2087 for (i=0; i<N; i++) { 2088 a->a[a->diag[rows[i]]] = diag; 2089 } 2090 } 2091 } 2092 ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2093 PetscFunctionReturn(0); 2094 } 2095 2096 PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 2097 { 2098 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2099 PetscInt *itmp; 2100 2101 PetscFunctionBegin; 2102 if (row < 0 || row >= A->rmap->n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row); 2103 2104 *nz = a->i[row+1] - a->i[row]; 2105 if (v) *v = a->a + a->i[row]; 2106 if (idx) { 2107 itmp = a->j + a->i[row]; 2108 if (*nz) *idx = itmp; 2109 else *idx = 0; 2110 } 2111 PetscFunctionReturn(0); 2112 } 2113 2114 /* remove this function? */ 2115 PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 2116 { 2117 PetscFunctionBegin; 2118 PetscFunctionReturn(0); 2119 } 2120 2121 PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm) 2122 { 2123 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2124 MatScalar *v = a->a; 2125 PetscReal sum = 0.0; 2126 PetscErrorCode ierr; 2127 PetscInt i,j; 2128 2129 PetscFunctionBegin; 2130 if (type == NORM_FROBENIUS) { 2131 #if defined(PETSC_USE_REAL___FP16) 2132 PetscBLASInt one = 1,nz = a->nz; 2133 *nrm = BLASnrm2_(&nz,v,&one); 2134 #else 2135 for (i=0; i<a->nz; i++) { 2136 sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 2137 } 2138 *nrm = PetscSqrtReal(sum); 2139 #endif 2140 ierr = PetscLogFlops(2*a->nz);CHKERRQ(ierr); 2141 } else if (type == NORM_1) { 2142 PetscReal *tmp; 2143 PetscInt *jj = a->j; 2144 ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr); 2145 *nrm = 0.0; 2146 for (j=0; j<a->nz; j++) { 2147 tmp[*jj++] += PetscAbsScalar(*v); v++; 2148 } 2149 for (j=0; j<A->cmap->n; j++) { 2150 if (tmp[j] > *nrm) *nrm = tmp[j]; 2151 } 2152 ierr = PetscFree(tmp);CHKERRQ(ierr); 2153 ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr); 2154 } else if (type == NORM_INFINITY) { 2155 *nrm = 0.0; 2156 for (j=0; j<A->rmap->n; j++) { 2157 v = a->a + a->i[j]; 2158 sum = 0.0; 2159 for (i=0; i<a->i[j+1]-a->i[j]; i++) { 2160 sum += PetscAbsScalar(*v); v++; 2161 } 2162 if (sum > *nrm) *nrm = sum; 2163 } 2164 ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr); 2165 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm"); 2166 PetscFunctionReturn(0); 2167 } 2168 2169 /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */ 2170 PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B) 2171 { 2172 PetscErrorCode ierr; 2173 PetscInt i,j,anzj; 2174 Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data,*b; 2175 PetscInt an=A->cmap->N,am=A->rmap->N; 2176 PetscInt *ati,*atj,*atfill,*ai=a->i,*aj=a->j; 2177 2178 PetscFunctionBegin; 2179 /* Allocate space for symbolic transpose info and work array */ 2180 ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr); 2181 ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr); 2182 ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr); 2183 2184 /* Walk through aj and count ## of non-zeros in each row of A^T. */ 2185 /* Note: offset by 1 for fast conversion into csr format. */ 2186 for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1; 2187 /* Form ati for csr format of A^T. */ 2188 for (i=0;i<an;i++) ati[i+1] += ati[i]; 2189 2190 /* Copy ati into atfill so we have locations of the next free space in atj */ 2191 ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr); 2192 2193 /* Walk through A row-wise and mark nonzero entries of A^T. */ 2194 for (i=0;i<am;i++) { 2195 anzj = ai[i+1] - ai[i]; 2196 for (j=0;j<anzj;j++) { 2197 atj[atfill[*aj]] = i; 2198 atfill[*aj++] += 1; 2199 } 2200 } 2201 2202 /* Clean up temporary space and complete requests. */ 2203 ierr = PetscFree(atfill);CHKERRQ(ierr); 2204 ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr); 2205 ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr); 2206 2207 b = (Mat_SeqAIJ*)((*B)->data); 2208 b->free_a = PETSC_FALSE; 2209 b->free_ij = PETSC_TRUE; 2210 b->nonew = 0; 2211 PetscFunctionReturn(0); 2212 } 2213 2214 PetscErrorCode MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f) 2215 { 2216 Mat_SeqAIJ *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data; 2217 PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr; 2218 MatScalar *va,*vb; 2219 PetscErrorCode ierr; 2220 PetscInt ma,na,mb,nb, i; 2221 2222 PetscFunctionBegin; 2223 ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr); 2224 ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr); 2225 if (ma!=nb || na!=mb) { 2226 *f = PETSC_FALSE; 2227 PetscFunctionReturn(0); 2228 } 2229 aii = aij->i; bii = bij->i; 2230 adx = aij->j; bdx = bij->j; 2231 va = aij->a; vb = bij->a; 2232 ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr); 2233 ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr); 2234 for (i=0; i<ma; i++) aptr[i] = aii[i]; 2235 for (i=0; i<mb; i++) bptr[i] = bii[i]; 2236 2237 *f = PETSC_TRUE; 2238 for (i=0; i<ma; i++) { 2239 while (aptr[i]<aii[i+1]) { 2240 PetscInt idc,idr; 2241 PetscScalar vc,vr; 2242 /* column/row index/value */ 2243 idc = adx[aptr[i]]; 2244 idr = bdx[bptr[idc]]; 2245 vc = va[aptr[i]]; 2246 vr = vb[bptr[idc]]; 2247 if (i!=idr || PetscAbsScalar(vc-vr) > tol) { 2248 *f = PETSC_FALSE; 2249 goto done; 2250 } else { 2251 aptr[i]++; 2252 if (B || i!=idc) bptr[idc]++; 2253 } 2254 } 2255 } 2256 done: 2257 ierr = PetscFree(aptr);CHKERRQ(ierr); 2258 ierr = PetscFree(bptr);CHKERRQ(ierr); 2259 PetscFunctionReturn(0); 2260 } 2261 2262 PetscErrorCode MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f) 2263 { 2264 Mat_SeqAIJ *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data; 2265 PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr; 2266 MatScalar *va,*vb; 2267 PetscErrorCode ierr; 2268 PetscInt ma,na,mb,nb, i; 2269 2270 PetscFunctionBegin; 2271 ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr); 2272 ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr); 2273 if (ma!=nb || na!=mb) { 2274 *f = PETSC_FALSE; 2275 PetscFunctionReturn(0); 2276 } 2277 aii = aij->i; bii = bij->i; 2278 adx = aij->j; bdx = bij->j; 2279 va = aij->a; vb = bij->a; 2280 ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr); 2281 ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr); 2282 for (i=0; i<ma; i++) aptr[i] = aii[i]; 2283 for (i=0; i<mb; i++) bptr[i] = bii[i]; 2284 2285 *f = PETSC_TRUE; 2286 for (i=0; i<ma; i++) { 2287 while (aptr[i]<aii[i+1]) { 2288 PetscInt idc,idr; 2289 PetscScalar vc,vr; 2290 /* column/row index/value */ 2291 idc = adx[aptr[i]]; 2292 idr = bdx[bptr[idc]]; 2293 vc = va[aptr[i]]; 2294 vr = vb[bptr[idc]]; 2295 if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) { 2296 *f = PETSC_FALSE; 2297 goto done; 2298 } else { 2299 aptr[i]++; 2300 if (B || i!=idc) bptr[idc]++; 2301 } 2302 } 2303 } 2304 done: 2305 ierr = PetscFree(aptr);CHKERRQ(ierr); 2306 ierr = PetscFree(bptr);CHKERRQ(ierr); 2307 PetscFunctionReturn(0); 2308 } 2309 2310 PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool *f) 2311 { 2312 PetscErrorCode ierr; 2313 2314 PetscFunctionBegin; 2315 ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr); 2316 PetscFunctionReturn(0); 2317 } 2318 2319 PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool *f) 2320 { 2321 PetscErrorCode ierr; 2322 2323 PetscFunctionBegin; 2324 ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr); 2325 PetscFunctionReturn(0); 2326 } 2327 2328 PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr) 2329 { 2330 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2331 const PetscScalar *l,*r; 2332 PetscScalar x; 2333 MatScalar *v; 2334 PetscErrorCode ierr; 2335 PetscInt i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz; 2336 const PetscInt *jj; 2337 2338 PetscFunctionBegin; 2339 if (ll) { 2340 /* The local size is used so that VecMPI can be passed to this routine 2341 by MatDiagonalScale_MPIAIJ */ 2342 ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr); 2343 if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length"); 2344 ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr); 2345 v = a->a; 2346 for (i=0; i<m; i++) { 2347 x = l[i]; 2348 M = a->i[i+1] - a->i[i]; 2349 for (j=0; j<M; j++) (*v++) *= x; 2350 } 2351 ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr); 2352 ierr = PetscLogFlops(nz);CHKERRQ(ierr); 2353 } 2354 if (rr) { 2355 ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr); 2356 if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length"); 2357 ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr); 2358 v = a->a; jj = a->j; 2359 for (i=0; i<nz; i++) (*v++) *= r[*jj++]; 2360 ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr); 2361 ierr = PetscLogFlops(nz);CHKERRQ(ierr); 2362 } 2363 ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr); 2364 PetscFunctionReturn(0); 2365 } 2366 2367 PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B) 2368 { 2369 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*c; 2370 PetscErrorCode ierr; 2371 PetscInt *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens; 2372 PetscInt row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi; 2373 const PetscInt *irow,*icol; 2374 PetscInt nrows,ncols; 2375 PetscInt *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen; 2376 MatScalar *a_new,*mat_a; 2377 Mat C; 2378 PetscBool stride; 2379 2380 PetscFunctionBegin; 2381 2382 ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr); 2383 ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr); 2384 ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr); 2385 2386 ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr); 2387 if (stride) { 2388 ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr); 2389 } else { 2390 first = 0; 2391 step = 0; 2392 } 2393 if (stride && step == 1) { 2394 /* special case of contiguous rows */ 2395 ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr); 2396 /* loop over new rows determining lens and starting points */ 2397 for (i=0; i<nrows; i++) { 2398 kstart = ai[irow[i]]; 2399 kend = kstart + ailen[irow[i]]; 2400 starts[i] = kstart; 2401 for (k=kstart; k<kend; k++) { 2402 if (aj[k] >= first) { 2403 starts[i] = k; 2404 break; 2405 } 2406 } 2407 sum = 0; 2408 while (k < kend) { 2409 if (aj[k++] >= first+ncols) break; 2410 sum++; 2411 } 2412 lens[i] = sum; 2413 } 2414 /* create submatrix */ 2415 if (scall == MAT_REUSE_MATRIX) { 2416 PetscInt n_cols,n_rows; 2417 ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr); 2418 if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size"); 2419 ierr = MatZeroEntries(*B);CHKERRQ(ierr); 2420 C = *B; 2421 } else { 2422 PetscInt rbs,cbs; 2423 ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 2424 ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 2425 ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr); 2426 ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr); 2427 ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr); 2428 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 2429 ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr); 2430 } 2431 c = (Mat_SeqAIJ*)C->data; 2432 2433 /* loop over rows inserting into submatrix */ 2434 a_new = c->a; 2435 j_new = c->j; 2436 i_new = c->i; 2437 2438 for (i=0; i<nrows; i++) { 2439 ii = starts[i]; 2440 lensi = lens[i]; 2441 for (k=0; k<lensi; k++) { 2442 *j_new++ = aj[ii+k] - first; 2443 } 2444 ierr = PetscArraycpy(a_new,a->a + starts[i],lensi);CHKERRQ(ierr); 2445 a_new += lensi; 2446 i_new[i+1] = i_new[i] + lensi; 2447 c->ilen[i] = lensi; 2448 } 2449 ierr = PetscFree2(lens,starts);CHKERRQ(ierr); 2450 } else { 2451 ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr); 2452 ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr); 2453 ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr); 2454 for (i=0; i<ncols; i++) { 2455 #if defined(PETSC_USE_DEBUG) 2456 if (icol[i] >= oldcols) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Requesting column beyond largest column icol[%D] %D <= A->cmap->n %D",i,icol[i],oldcols); 2457 #endif 2458 smap[icol[i]] = i+1; 2459 } 2460 2461 /* determine lens of each row */ 2462 for (i=0; i<nrows; i++) { 2463 kstart = ai[irow[i]]; 2464 kend = kstart + a->ilen[irow[i]]; 2465 lens[i] = 0; 2466 for (k=kstart; k<kend; k++) { 2467 if (smap[aj[k]]) { 2468 lens[i]++; 2469 } 2470 } 2471 } 2472 /* Create and fill new matrix */ 2473 if (scall == MAT_REUSE_MATRIX) { 2474 PetscBool equal; 2475 2476 c = (Mat_SeqAIJ*)((*B)->data); 2477 if ((*B)->rmap->n != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size"); 2478 ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr); 2479 if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros"); 2480 ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr); 2481 C = *B; 2482 } else { 2483 PetscInt rbs,cbs; 2484 ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 2485 ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 2486 ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr); 2487 ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr); 2488 ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr); 2489 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 2490 ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr); 2491 } 2492 c = (Mat_SeqAIJ*)(C->data); 2493 for (i=0; i<nrows; i++) { 2494 row = irow[i]; 2495 kstart = ai[row]; 2496 kend = kstart + a->ilen[row]; 2497 mat_i = c->i[i]; 2498 mat_j = c->j + mat_i; 2499 mat_a = c->a + mat_i; 2500 mat_ilen = c->ilen + i; 2501 for (k=kstart; k<kend; k++) { 2502 if ((tcol=smap[a->j[k]])) { 2503 *mat_j++ = tcol - 1; 2504 *mat_a++ = a->a[k]; 2505 (*mat_ilen)++; 2506 2507 } 2508 } 2509 } 2510 /* Free work space */ 2511 ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr); 2512 ierr = PetscFree(smap);CHKERRQ(ierr); 2513 ierr = PetscFree(lens);CHKERRQ(ierr); 2514 /* sort */ 2515 for (i = 0; i < nrows; i++) { 2516 PetscInt ilen; 2517 2518 mat_i = c->i[i]; 2519 mat_j = c->j + mat_i; 2520 mat_a = c->a + mat_i; 2521 ilen = c->ilen[i]; 2522 ierr = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr); 2523 } 2524 } 2525 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2526 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2527 2528 ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr); 2529 *B = C; 2530 PetscFunctionReturn(0); 2531 } 2532 2533 PetscErrorCode MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat) 2534 { 2535 PetscErrorCode ierr; 2536 Mat B; 2537 2538 PetscFunctionBegin; 2539 if (scall == MAT_INITIAL_MATRIX) { 2540 ierr = MatCreate(subComm,&B);CHKERRQ(ierr); 2541 ierr = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr); 2542 ierr = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr); 2543 ierr = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr); 2544 ierr = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr); 2545 *subMat = B; 2546 } else { 2547 ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 2548 } 2549 PetscFunctionReturn(0); 2550 } 2551 2552 PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info) 2553 { 2554 Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 2555 PetscErrorCode ierr; 2556 Mat outA; 2557 PetscBool row_identity,col_identity; 2558 2559 PetscFunctionBegin; 2560 if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu"); 2561 2562 ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr); 2563 ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr); 2564 2565 outA = inA; 2566 outA->factortype = MAT_FACTOR_LU; 2567 ierr = PetscFree(inA->solvertype);CHKERRQ(ierr); 2568 ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr); 2569 2570 ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr); 2571 ierr = ISDestroy(&a->row);CHKERRQ(ierr); 2572 2573 a->row = row; 2574 2575 ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr); 2576 ierr = ISDestroy(&a->col);CHKERRQ(ierr); 2577 2578 a->col = col; 2579 2580 /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */ 2581 ierr = ISDestroy(&a->icol);CHKERRQ(ierr); 2582 ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr); 2583 ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr); 2584 2585 if (!a->solve_work) { /* this matrix may have been factored before */ 2586 ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr); 2587 ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr); 2588 } 2589 2590 ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr); 2591 if (row_identity && col_identity) { 2592 ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr); 2593 } else { 2594 ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr); 2595 } 2596 PetscFunctionReturn(0); 2597 } 2598 2599 PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha) 2600 { 2601 Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 2602 PetscScalar oalpha = alpha; 2603 PetscErrorCode ierr; 2604 PetscBLASInt one = 1,bnz; 2605 2606 PetscFunctionBegin; 2607 ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr); 2608 PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&oalpha,a->a,&one)); 2609 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 2610 ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr); 2611 PetscFunctionReturn(0); 2612 } 2613 2614 PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj) 2615 { 2616 PetscErrorCode ierr; 2617 PetscInt i; 2618 2619 PetscFunctionBegin; 2620 if (!submatj->id) { /* delete data that are linked only to submats[id=0] */ 2621 ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr); 2622 2623 for (i=0; i<submatj->nrqr; ++i) { 2624 ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr); 2625 } 2626 ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr); 2627 2628 if (submatj->rbuf1) { 2629 ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr); 2630 ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr); 2631 } 2632 2633 for (i=0; i<submatj->nrqs; ++i) { 2634 ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr); 2635 } 2636 ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr); 2637 ierr = PetscFree(submatj->pa);CHKERRQ(ierr); 2638 } 2639 2640 #if defined(PETSC_USE_CTABLE) 2641 ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr); 2642 if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);} 2643 ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr); 2644 #else 2645 ierr = PetscFree(submatj->rmap);CHKERRQ(ierr); 2646 #endif 2647 2648 if (!submatj->allcolumns) { 2649 #if defined(PETSC_USE_CTABLE) 2650 ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr); 2651 #else 2652 ierr = PetscFree(submatj->cmap);CHKERRQ(ierr); 2653 #endif 2654 } 2655 ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr); 2656 2657 ierr = PetscFree(submatj);CHKERRQ(ierr); 2658 PetscFunctionReturn(0); 2659 } 2660 2661 PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C) 2662 { 2663 PetscErrorCode ierr; 2664 Mat_SeqAIJ *c = (Mat_SeqAIJ*)C->data; 2665 Mat_SubSppt *submatj = c->submatis1; 2666 2667 PetscFunctionBegin; 2668 ierr = (*submatj->destroy)(C);CHKERRQ(ierr); 2669 ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr); 2670 PetscFunctionReturn(0); 2671 } 2672 2673 PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[]) 2674 { 2675 PetscErrorCode ierr; 2676 PetscInt i; 2677 Mat C; 2678 Mat_SeqAIJ *c; 2679 Mat_SubSppt *submatj; 2680 2681 PetscFunctionBegin; 2682 for (i=0; i<n; i++) { 2683 C = (*mat)[i]; 2684 c = (Mat_SeqAIJ*)C->data; 2685 submatj = c->submatis1; 2686 if (submatj) { 2687 if (--((PetscObject)C)->refct <= 0) { 2688 ierr = (*submatj->destroy)(C);CHKERRQ(ierr); 2689 ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr); 2690 ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr); 2691 ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr); 2692 ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr); 2693 ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr); 2694 } 2695 } else { 2696 ierr = MatDestroy(&C);CHKERRQ(ierr); 2697 } 2698 } 2699 2700 /* Destroy Dummy submatrices created for reuse */ 2701 ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr); 2702 2703 ierr = PetscFree(*mat);CHKERRQ(ierr); 2704 PetscFunctionReturn(0); 2705 } 2706 2707 PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[]) 2708 { 2709 PetscErrorCode ierr; 2710 PetscInt i; 2711 2712 PetscFunctionBegin; 2713 if (scall == MAT_INITIAL_MATRIX) { 2714 ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr); 2715 } 2716 2717 for (i=0; i<n; i++) { 2718 ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr); 2719 } 2720 PetscFunctionReturn(0); 2721 } 2722 2723 PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov) 2724 { 2725 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2726 PetscErrorCode ierr; 2727 PetscInt row,i,j,k,l,m,n,*nidx,isz,val; 2728 const PetscInt *idx; 2729 PetscInt start,end,*ai,*aj; 2730 PetscBT table; 2731 2732 PetscFunctionBegin; 2733 m = A->rmap->n; 2734 ai = a->i; 2735 aj = a->j; 2736 2737 if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used"); 2738 2739 ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr); 2740 ierr = PetscBTCreate(m,&table);CHKERRQ(ierr); 2741 2742 for (i=0; i<is_max; i++) { 2743 /* Initialize the two local arrays */ 2744 isz = 0; 2745 ierr = PetscBTMemzero(m,table);CHKERRQ(ierr); 2746 2747 /* Extract the indices, assume there can be duplicate entries */ 2748 ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr); 2749 ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr); 2750 2751 /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 2752 for (j=0; j<n; ++j) { 2753 if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j]; 2754 } 2755 ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr); 2756 ierr = ISDestroy(&is[i]);CHKERRQ(ierr); 2757 2758 k = 0; 2759 for (j=0; j<ov; j++) { /* for each overlap */ 2760 n = isz; 2761 for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */ 2762 row = nidx[k]; 2763 start = ai[row]; 2764 end = ai[row+1]; 2765 for (l = start; l<end; l++) { 2766 val = aj[l]; 2767 if (!PetscBTLookupSet(table,val)) nidx[isz++] = val; 2768 } 2769 } 2770 } 2771 ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr); 2772 } 2773 ierr = PetscBTDestroy(&table);CHKERRQ(ierr); 2774 ierr = PetscFree(nidx);CHKERRQ(ierr); 2775 PetscFunctionReturn(0); 2776 } 2777 2778 /* -------------------------------------------------------------- */ 2779 PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B) 2780 { 2781 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2782 PetscErrorCode ierr; 2783 PetscInt i,nz = 0,m = A->rmap->n,n = A->cmap->n; 2784 const PetscInt *row,*col; 2785 PetscInt *cnew,j,*lens; 2786 IS icolp,irowp; 2787 PetscInt *cwork = NULL; 2788 PetscScalar *vwork = NULL; 2789 2790 PetscFunctionBegin; 2791 ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr); 2792 ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr); 2793 ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr); 2794 ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr); 2795 2796 /* determine lengths of permuted rows */ 2797 ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr); 2798 for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i]; 2799 ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr); 2800 ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr); 2801 ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr); 2802 ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr); 2803 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr); 2804 ierr = PetscFree(lens);CHKERRQ(ierr); 2805 2806 ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr); 2807 for (i=0; i<m; i++) { 2808 ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr); 2809 for (j=0; j<nz; j++) cnew[j] = col[cwork[j]]; 2810 ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr); 2811 ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr); 2812 } 2813 ierr = PetscFree(cnew);CHKERRQ(ierr); 2814 2815 (*B)->assembled = PETSC_FALSE; 2816 2817 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2818 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2819 ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr); 2820 ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr); 2821 ierr = ISDestroy(&irowp);CHKERRQ(ierr); 2822 ierr = ISDestroy(&icolp);CHKERRQ(ierr); 2823 PetscFunctionReturn(0); 2824 } 2825 2826 PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str) 2827 { 2828 PetscErrorCode ierr; 2829 2830 PetscFunctionBegin; 2831 /* If the two matrices have the same copy implementation, use fast copy. */ 2832 if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) { 2833 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2834 Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 2835 2836 if (a->i[A->rmap->n] != b->i[B->rmap->n]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different"); 2837 ierr = PetscArraycpy(b->a,a->a,a->i[A->rmap->n]);CHKERRQ(ierr); 2838 ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr); 2839 } else { 2840 ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr); 2841 } 2842 PetscFunctionReturn(0); 2843 } 2844 2845 PetscErrorCode MatSetUp_SeqAIJ(Mat A) 2846 { 2847 PetscErrorCode ierr; 2848 2849 PetscFunctionBegin; 2850 ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,0);CHKERRQ(ierr); 2851 PetscFunctionReturn(0); 2852 } 2853 2854 PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[]) 2855 { 2856 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2857 2858 PetscFunctionBegin; 2859 *array = a->a; 2860 PetscFunctionReturn(0); 2861 } 2862 2863 PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[]) 2864 { 2865 PetscFunctionBegin; 2866 PetscFunctionReturn(0); 2867 } 2868 2869 /* 2870 Computes the number of nonzeros per row needed for preallocation when X and Y 2871 have different nonzero structure. 2872 */ 2873 PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz) 2874 { 2875 PetscInt i,j,k,nzx,nzy; 2876 2877 PetscFunctionBegin; 2878 /* Set the number of nonzeros in the new matrix */ 2879 for (i=0; i<m; i++) { 2880 const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i]; 2881 nzx = xi[i+1] - xi[i]; 2882 nzy = yi[i+1] - yi[i]; 2883 nnz[i] = 0; 2884 for (j=0,k=0; j<nzx; j++) { /* Point in X */ 2885 for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */ 2886 if (k<nzy && yjj[k]==xjj[j]) k++; /* Skip duplicate */ 2887 nnz[i]++; 2888 } 2889 for (; k<nzy; k++) nnz[i]++; 2890 } 2891 PetscFunctionReturn(0); 2892 } 2893 2894 PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz) 2895 { 2896 PetscInt m = Y->rmap->N; 2897 Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data; 2898 Mat_SeqAIJ *y = (Mat_SeqAIJ*)Y->data; 2899 PetscErrorCode ierr; 2900 2901 PetscFunctionBegin; 2902 /* Set the number of nonzeros in the new matrix */ 2903 ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr); 2904 PetscFunctionReturn(0); 2905 } 2906 2907 PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str) 2908 { 2909 PetscErrorCode ierr; 2910 Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data; 2911 PetscBLASInt one=1,bnz; 2912 2913 PetscFunctionBegin; 2914 ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr); 2915 if (str == SAME_NONZERO_PATTERN) { 2916 PetscScalar alpha = a; 2917 PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one)); 2918 ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr); 2919 ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr); 2920 } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 2921 ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr); 2922 } else { 2923 Mat B; 2924 PetscInt *nnz; 2925 ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr); 2926 ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr); 2927 ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr); 2928 ierr = MatSetSizes(B,Y->rmap->n,Y->cmap->n,Y->rmap->N,Y->cmap->N);CHKERRQ(ierr); 2929 ierr = MatSetBlockSizesFromMats(B,Y,Y);CHKERRQ(ierr); 2930 ierr = MatSetType(B,(MatType) ((PetscObject)Y)->type_name);CHKERRQ(ierr); 2931 ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr); 2932 ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr); 2933 ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr); 2934 ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr); 2935 ierr = PetscFree(nnz);CHKERRQ(ierr); 2936 } 2937 PetscFunctionReturn(0); 2938 } 2939 2940 PetscErrorCode MatConjugate_SeqAIJ(Mat mat) 2941 { 2942 #if defined(PETSC_USE_COMPLEX) 2943 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 2944 PetscInt i,nz; 2945 PetscScalar *a; 2946 2947 PetscFunctionBegin; 2948 nz = aij->nz; 2949 a = aij->a; 2950 for (i=0; i<nz; i++) a[i] = PetscConj(a[i]); 2951 #else 2952 PetscFunctionBegin; 2953 #endif 2954 PetscFunctionReturn(0); 2955 } 2956 2957 PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2958 { 2959 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2960 PetscErrorCode ierr; 2961 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2962 PetscReal atmp; 2963 PetscScalar *x; 2964 MatScalar *aa; 2965 2966 PetscFunctionBegin; 2967 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2968 aa = a->a; 2969 ai = a->i; 2970 aj = a->j; 2971 2972 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2973 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2974 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 2975 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2976 for (i=0; i<m; i++) { 2977 ncols = ai[1] - ai[0]; ai++; 2978 x[i] = 0.0; 2979 for (j=0; j<ncols; j++) { 2980 atmp = PetscAbsScalar(*aa); 2981 if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;} 2982 aa++; aj++; 2983 } 2984 } 2985 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2986 PetscFunctionReturn(0); 2987 } 2988 2989 PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2990 { 2991 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2992 PetscErrorCode ierr; 2993 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2994 PetscScalar *x; 2995 MatScalar *aa; 2996 2997 PetscFunctionBegin; 2998 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2999 aa = a->a; 3000 ai = a->i; 3001 aj = a->j; 3002 3003 ierr = VecSet(v,0.0);CHKERRQ(ierr); 3004 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 3005 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 3006 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 3007 for (i=0; i<m; i++) { 3008 ncols = ai[1] - ai[0]; ai++; 3009 if (ncols == A->cmap->n) { /* row is dense */ 3010 x[i] = *aa; if (idx) idx[i] = 0; 3011 } else { /* row is sparse so already KNOW maximum is 0.0 or higher */ 3012 x[i] = 0.0; 3013 if (idx) { 3014 idx[i] = 0; /* in case ncols is zero */ 3015 for (j=0;j<ncols;j++) { /* find first implicit 0.0 in the row */ 3016 if (aj[j] > j) { 3017 idx[i] = j; 3018 break; 3019 } 3020 } 3021 } 3022 } 3023 for (j=0; j<ncols; j++) { 3024 if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 3025 aa++; aj++; 3026 } 3027 } 3028 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 3029 PetscFunctionReturn(0); 3030 } 3031 3032 PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3033 { 3034 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3035 PetscErrorCode ierr; 3036 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 3037 PetscReal atmp; 3038 PetscScalar *x; 3039 MatScalar *aa; 3040 3041 PetscFunctionBegin; 3042 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3043 aa = a->a; 3044 ai = a->i; 3045 aj = a->j; 3046 3047 ierr = VecSet(v,0.0);CHKERRQ(ierr); 3048 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 3049 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 3050 if (n != A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %D vs. %D rows", A->rmap->n, n); 3051 for (i=0; i<m; i++) { 3052 ncols = ai[1] - ai[0]; ai++; 3053 if (ncols) { 3054 /* Get first nonzero */ 3055 for (j = 0; j < ncols; j++) { 3056 atmp = PetscAbsScalar(aa[j]); 3057 if (atmp > 1.0e-12) { 3058 x[i] = atmp; 3059 if (idx) idx[i] = aj[j]; 3060 break; 3061 } 3062 } 3063 if (j == ncols) {x[i] = PetscAbsScalar(*aa); if (idx) idx[i] = *aj;} 3064 } else { 3065 x[i] = 0.0; if (idx) idx[i] = 0; 3066 } 3067 for (j = 0; j < ncols; j++) { 3068 atmp = PetscAbsScalar(*aa); 3069 if (atmp > 1.0e-12 && PetscAbsScalar(x[i]) > atmp) {x[i] = atmp; if (idx) idx[i] = *aj;} 3070 aa++; aj++; 3071 } 3072 } 3073 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 3074 PetscFunctionReturn(0); 3075 } 3076 3077 PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3078 { 3079 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3080 PetscErrorCode ierr; 3081 PetscInt i,j,m = A->rmap->n,ncols,n; 3082 const PetscInt *ai,*aj; 3083 PetscScalar *x; 3084 const MatScalar *aa; 3085 3086 PetscFunctionBegin; 3087 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3088 aa = a->a; 3089 ai = a->i; 3090 aj = a->j; 3091 3092 ierr = VecSet(v,0.0);CHKERRQ(ierr); 3093 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 3094 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 3095 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 3096 for (i=0; i<m; i++) { 3097 ncols = ai[1] - ai[0]; ai++; 3098 if (ncols == A->cmap->n) { /* row is dense */ 3099 x[i] = *aa; if (idx) idx[i] = 0; 3100 } else { /* row is sparse so already KNOW minimum is 0.0 or lower */ 3101 x[i] = 0.0; 3102 if (idx) { /* find first implicit 0.0 in the row */ 3103 idx[i] = 0; /* in case ncols is zero */ 3104 for (j=0; j<ncols; j++) { 3105 if (aj[j] > j) { 3106 idx[i] = j; 3107 break; 3108 } 3109 } 3110 } 3111 } 3112 for (j=0; j<ncols; j++) { 3113 if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 3114 aa++; aj++; 3115 } 3116 } 3117 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 3118 PetscFunctionReturn(0); 3119 } 3120 3121 PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values) 3122 { 3123 Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 3124 PetscErrorCode ierr; 3125 PetscInt i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j; 3126 MatScalar *diag,work[25],*v_work; 3127 const PetscReal shift = 0.0; 3128 PetscBool allowzeropivot,zeropivotdetected=PETSC_FALSE; 3129 3130 PetscFunctionBegin; 3131 allowzeropivot = PetscNot(A->erroriffailure); 3132 if (a->ibdiagvalid) { 3133 if (values) *values = a->ibdiag; 3134 PetscFunctionReturn(0); 3135 } 3136 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 3137 if (!a->ibdiag) { 3138 ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr); 3139 ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr); 3140 } 3141 diag = a->ibdiag; 3142 if (values) *values = a->ibdiag; 3143 /* factor and invert each block */ 3144 switch (bs) { 3145 case 1: 3146 for (i=0; i<mbs; i++) { 3147 ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr); 3148 if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) { 3149 if (allowzeropivot) { 3150 A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3151 A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]); 3152 A->factorerror_zeropivot_row = i; 3153 ierr = PetscInfo3(A,"Zero pivot, row %D pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr); 3154 } else SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_MAT_LU_ZRPVT,"Zero pivot, row %D pivot %g tolerance %g",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON); 3155 } 3156 diag[i] = (PetscScalar)1.0 / (diag[i] + shift); 3157 } 3158 break; 3159 case 2: 3160 for (i=0; i<mbs; i++) { 3161 ij[0] = 2*i; ij[1] = 2*i + 1; 3162 ierr = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr); 3163 ierr = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 3164 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3165 ierr = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr); 3166 diag += 4; 3167 } 3168 break; 3169 case 3: 3170 for (i=0; i<mbs; i++) { 3171 ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2; 3172 ierr = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr); 3173 ierr = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 3174 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3175 ierr = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr); 3176 diag += 9; 3177 } 3178 break; 3179 case 4: 3180 for (i=0; i<mbs; i++) { 3181 ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3; 3182 ierr = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr); 3183 ierr = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 3184 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3185 ierr = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr); 3186 diag += 16; 3187 } 3188 break; 3189 case 5: 3190 for (i=0; i<mbs; i++) { 3191 ij[0] = 5*i; ij[1] = 5*i + 1; ij[2] = 5*i + 2; ij[3] = 5*i + 3; ij[4] = 5*i + 4; 3192 ierr = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr); 3193 ierr = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 3194 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3195 ierr = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr); 3196 diag += 25; 3197 } 3198 break; 3199 case 6: 3200 for (i=0; i<mbs; i++) { 3201 ij[0] = 6*i; ij[1] = 6*i + 1; ij[2] = 6*i + 2; ij[3] = 6*i + 3; ij[4] = 6*i + 4; ij[5] = 6*i + 5; 3202 ierr = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr); 3203 ierr = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 3204 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3205 ierr = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr); 3206 diag += 36; 3207 } 3208 break; 3209 case 7: 3210 for (i=0; i<mbs; i++) { 3211 ij[0] = 7*i; ij[1] = 7*i + 1; ij[2] = 7*i + 2; ij[3] = 7*i + 3; ij[4] = 7*i + 4; ij[5] = 7*i + 5; ij[5] = 7*i + 6; 3212 ierr = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr); 3213 ierr = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 3214 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3215 ierr = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr); 3216 diag += 49; 3217 } 3218 break; 3219 default: 3220 ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr); 3221 for (i=0; i<mbs; i++) { 3222 for (j=0; j<bs; j++) { 3223 IJ[j] = bs*i + j; 3224 } 3225 ierr = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr); 3226 ierr = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 3227 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3228 ierr = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr); 3229 diag += bs2; 3230 } 3231 ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr); 3232 } 3233 a->ibdiagvalid = PETSC_TRUE; 3234 PetscFunctionReturn(0); 3235 } 3236 3237 static PetscErrorCode MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx) 3238 { 3239 PetscErrorCode ierr; 3240 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)x->data; 3241 PetscScalar a; 3242 PetscInt m,n,i,j,col; 3243 3244 PetscFunctionBegin; 3245 if (!x->assembled) { 3246 ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr); 3247 for (i=0; i<m; i++) { 3248 for (j=0; j<aij->imax[i]; j++) { 3249 ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr); 3250 col = (PetscInt)(n*PetscRealPart(a)); 3251 ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr); 3252 } 3253 } 3254 } else { 3255 for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aij->a+i);CHKERRQ(ierr);} 3256 } 3257 ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3258 ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3259 PetscFunctionReturn(0); 3260 } 3261 3262 /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */ 3263 PetscErrorCode MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx) 3264 { 3265 PetscErrorCode ierr; 3266 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)x->data; 3267 PetscScalar a; 3268 PetscInt m,n,i,j,col,nskip; 3269 3270 PetscFunctionBegin; 3271 nskip = high - low; 3272 ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr); 3273 n -= nskip; /* shrink number of columns where nonzeros can be set */ 3274 for (i=0; i<m; i++) { 3275 for (j=0; j<aij->imax[i]; j++) { 3276 ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr); 3277 col = (PetscInt)(n*PetscRealPart(a)); 3278 if (col >= low) col += nskip; /* shift col rightward to skip the hole */ 3279 ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr); 3280 } 3281 } 3282 ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3283 ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3284 PetscFunctionReturn(0); 3285 } 3286 3287 3288 /* -------------------------------------------------------------------*/ 3289 static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ, 3290 MatGetRow_SeqAIJ, 3291 MatRestoreRow_SeqAIJ, 3292 MatMult_SeqAIJ, 3293 /* 4*/ MatMultAdd_SeqAIJ, 3294 MatMultTranspose_SeqAIJ, 3295 MatMultTransposeAdd_SeqAIJ, 3296 0, 3297 0, 3298 0, 3299 /* 10*/ 0, 3300 MatLUFactor_SeqAIJ, 3301 0, 3302 MatSOR_SeqAIJ, 3303 MatTranspose_SeqAIJ, 3304 /*1 5*/ MatGetInfo_SeqAIJ, 3305 MatEqual_SeqAIJ, 3306 MatGetDiagonal_SeqAIJ, 3307 MatDiagonalScale_SeqAIJ, 3308 MatNorm_SeqAIJ, 3309 /* 20*/ 0, 3310 MatAssemblyEnd_SeqAIJ, 3311 MatSetOption_SeqAIJ, 3312 MatZeroEntries_SeqAIJ, 3313 /* 24*/ MatZeroRows_SeqAIJ, 3314 0, 3315 0, 3316 0, 3317 0, 3318 /* 29*/ MatSetUp_SeqAIJ, 3319 0, 3320 0, 3321 0, 3322 0, 3323 /* 34*/ MatDuplicate_SeqAIJ, 3324 0, 3325 0, 3326 MatILUFactor_SeqAIJ, 3327 0, 3328 /* 39*/ MatAXPY_SeqAIJ, 3329 MatCreateSubMatrices_SeqAIJ, 3330 MatIncreaseOverlap_SeqAIJ, 3331 MatGetValues_SeqAIJ, 3332 MatCopy_SeqAIJ, 3333 /* 44*/ MatGetRowMax_SeqAIJ, 3334 MatScale_SeqAIJ, 3335 MatShift_SeqAIJ, 3336 MatDiagonalSet_SeqAIJ, 3337 MatZeroRowsColumns_SeqAIJ, 3338 /* 49*/ MatSetRandom_SeqAIJ, 3339 MatGetRowIJ_SeqAIJ, 3340 MatRestoreRowIJ_SeqAIJ, 3341 MatGetColumnIJ_SeqAIJ, 3342 MatRestoreColumnIJ_SeqAIJ, 3343 /* 54*/ MatFDColoringCreate_SeqXAIJ, 3344 0, 3345 0, 3346 MatPermute_SeqAIJ, 3347 0, 3348 /* 59*/ 0, 3349 MatDestroy_SeqAIJ, 3350 MatView_SeqAIJ, 3351 0, 3352 MatMatMatMult_SeqAIJ_SeqAIJ_SeqAIJ, 3353 /* 64*/ MatMatMatMultSymbolic_SeqAIJ_SeqAIJ_SeqAIJ, 3354 MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ, 3355 0, 3356 0, 3357 0, 3358 /* 69*/ MatGetRowMaxAbs_SeqAIJ, 3359 MatGetRowMinAbs_SeqAIJ, 3360 0, 3361 0, 3362 0, 3363 /* 74*/ 0, 3364 MatFDColoringApply_AIJ, 3365 0, 3366 0, 3367 0, 3368 /* 79*/ MatFindZeroDiagonals_SeqAIJ, 3369 0, 3370 0, 3371 0, 3372 MatLoad_SeqAIJ, 3373 /* 84*/ MatIsSymmetric_SeqAIJ, 3374 MatIsHermitian_SeqAIJ, 3375 0, 3376 0, 3377 0, 3378 /* 89*/ MatMatMult_SeqAIJ_SeqAIJ, 3379 MatMatMultSymbolic_SeqAIJ_SeqAIJ, 3380 MatMatMultNumeric_SeqAIJ_SeqAIJ, 3381 MatPtAP_SeqAIJ_SeqAIJ, 3382 MatPtAPSymbolic_SeqAIJ_SeqAIJ_SparseAxpy, 3383 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy, 3384 MatMatTransposeMult_SeqAIJ_SeqAIJ, 3385 MatMatTransposeMultSymbolic_SeqAIJ_SeqAIJ, 3386 MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ, 3387 0, 3388 /* 99*/ 0, 3389 0, 3390 0, 3391 MatConjugate_SeqAIJ, 3392 0, 3393 /*104*/ MatSetValuesRow_SeqAIJ, 3394 MatRealPart_SeqAIJ, 3395 MatImaginaryPart_SeqAIJ, 3396 0, 3397 0, 3398 /*109*/ MatMatSolve_SeqAIJ, 3399 0, 3400 MatGetRowMin_SeqAIJ, 3401 0, 3402 MatMissingDiagonal_SeqAIJ, 3403 /*114*/ 0, 3404 0, 3405 0, 3406 0, 3407 0, 3408 /*119*/ 0, 3409 0, 3410 0, 3411 0, 3412 MatGetMultiProcBlock_SeqAIJ, 3413 /*124*/ MatFindNonzeroRows_SeqAIJ, 3414 MatGetColumnNorms_SeqAIJ, 3415 MatInvertBlockDiagonal_SeqAIJ, 3416 MatInvertVariableBlockDiagonal_SeqAIJ, 3417 0, 3418 /*129*/ 0, 3419 MatTransposeMatMult_SeqAIJ_SeqAIJ, 3420 MatTransposeMatMultSymbolic_SeqAIJ_SeqAIJ, 3421 MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ, 3422 MatTransposeColoringCreate_SeqAIJ, 3423 /*134*/ MatTransColoringApplySpToDen_SeqAIJ, 3424 MatTransColoringApplyDenToSp_SeqAIJ, 3425 MatRARt_SeqAIJ_SeqAIJ, 3426 MatRARtSymbolic_SeqAIJ_SeqAIJ, 3427 MatRARtNumeric_SeqAIJ_SeqAIJ, 3428 /*139*/0, 3429 0, 3430 0, 3431 MatFDColoringSetUp_SeqXAIJ, 3432 MatFindOffBlockDiagonalEntries_SeqAIJ, 3433 /*144*/MatCreateMPIMatConcatenateSeqMat_SeqAIJ, 3434 MatDestroySubMatrices_SeqAIJ 3435 }; 3436 3437 PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices) 3438 { 3439 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3440 PetscInt i,nz,n; 3441 3442 PetscFunctionBegin; 3443 nz = aij->maxnz; 3444 n = mat->rmap->n; 3445 for (i=0; i<nz; i++) { 3446 aij->j[i] = indices[i]; 3447 } 3448 aij->nz = nz; 3449 for (i=0; i<n; i++) { 3450 aij->ilen[i] = aij->imax[i]; 3451 } 3452 PetscFunctionReturn(0); 3453 } 3454 3455 /* 3456 * When a sparse matrix has many zero columns, we should compact them out to save the space 3457 * This happens in MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable() 3458 * */ 3459 PetscErrorCode MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping) 3460 { 3461 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3462 PetscTable gid1_lid1; 3463 PetscTablePosition tpos; 3464 PetscInt gid,lid,i,j,ncols,ec; 3465 PetscInt *garray; 3466 PetscErrorCode ierr; 3467 3468 PetscFunctionBegin; 3469 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3470 PetscValidPointer(mapping,2); 3471 /* use a table */ 3472 ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr); 3473 ec = 0; 3474 for (i=0; i<mat->rmap->n; i++) { 3475 ncols = aij->i[i+1] - aij->i[i]; 3476 for (j=0; j<ncols; j++) { 3477 PetscInt data,gid1 = aij->j[aij->i[i] + j] + 1; 3478 ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr); 3479 if (!data) { 3480 /* one based table */ 3481 ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr); 3482 } 3483 } 3484 } 3485 /* form array of columns we need */ 3486 ierr = PetscMalloc1(ec+1,&garray);CHKERRQ(ierr); 3487 ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr); 3488 while (tpos) { 3489 ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr); 3490 gid--; 3491 lid--; 3492 garray[lid] = gid; 3493 } 3494 ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */ 3495 ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr); 3496 for (i=0; i<ec; i++) { 3497 ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr); 3498 } 3499 /* compact out the extra columns in B */ 3500 for (i=0; i<mat->rmap->n; i++) { 3501 ncols = aij->i[i+1] - aij->i[i]; 3502 for (j=0; j<ncols; j++) { 3503 PetscInt gid1 = aij->j[aij->i[i] + j] + 1; 3504 ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr); 3505 lid--; 3506 aij->j[aij->i[i] + j] = lid; 3507 } 3508 } 3509 mat->cmap->n = mat->cmap->N = ec; 3510 mat->cmap->bs = 1; 3511 3512 ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr); 3513 ierr = PetscLayoutSetUp((mat->cmap));CHKERRQ(ierr); 3514 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr); 3515 ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 3516 PetscFunctionReturn(0); 3517 } 3518 3519 /*@ 3520 MatSeqAIJSetColumnIndices - Set the column indices for all the rows 3521 in the matrix. 3522 3523 Input Parameters: 3524 + mat - the SeqAIJ matrix 3525 - indices - the column indices 3526 3527 Level: advanced 3528 3529 Notes: 3530 This can be called if you have precomputed the nonzero structure of the 3531 matrix and want to provide it to the matrix object to improve the performance 3532 of the MatSetValues() operation. 3533 3534 You MUST have set the correct numbers of nonzeros per row in the call to 3535 MatCreateSeqAIJ(), and the columns indices MUST be sorted. 3536 3537 MUST be called before any calls to MatSetValues(); 3538 3539 The indices should start with zero, not one. 3540 3541 @*/ 3542 PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices) 3543 { 3544 PetscErrorCode ierr; 3545 3546 PetscFunctionBegin; 3547 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3548 PetscValidPointer(indices,2); 3549 ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr); 3550 PetscFunctionReturn(0); 3551 } 3552 3553 /* ----------------------------------------------------------------------------------------*/ 3554 3555 PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) 3556 { 3557 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3558 PetscErrorCode ierr; 3559 size_t nz = aij->i[mat->rmap->n]; 3560 3561 PetscFunctionBegin; 3562 if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3563 3564 /* allocate space for values if not already there */ 3565 if (!aij->saved_values) { 3566 ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr); 3567 ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr); 3568 } 3569 3570 /* copy values over */ 3571 ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr); 3572 PetscFunctionReturn(0); 3573 } 3574 3575 /*@ 3576 MatStoreValues - Stashes a copy of the matrix values; this allows, for 3577 example, reuse of the linear part of a Jacobian, while recomputing the 3578 nonlinear portion. 3579 3580 Collect on Mat 3581 3582 Input Parameters: 3583 . mat - the matrix (currently only AIJ matrices support this option) 3584 3585 Level: advanced 3586 3587 Common Usage, with SNESSolve(): 3588 $ Create Jacobian matrix 3589 $ Set linear terms into matrix 3590 $ Apply boundary conditions to matrix, at this time matrix must have 3591 $ final nonzero structure (i.e. setting the nonlinear terms and applying 3592 $ boundary conditions again will not change the nonzero structure 3593 $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3594 $ ierr = MatStoreValues(mat); 3595 $ Call SNESSetJacobian() with matrix 3596 $ In your Jacobian routine 3597 $ ierr = MatRetrieveValues(mat); 3598 $ Set nonlinear terms in matrix 3599 3600 Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself: 3601 $ // build linear portion of Jacobian 3602 $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3603 $ ierr = MatStoreValues(mat); 3604 $ loop over nonlinear iterations 3605 $ ierr = MatRetrieveValues(mat); 3606 $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian 3607 $ // call MatAssemblyBegin/End() on matrix 3608 $ Solve linear system with Jacobian 3609 $ endloop 3610 3611 Notes: 3612 Matrix must already be assemblied before calling this routine 3613 Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before 3614 calling this routine. 3615 3616 When this is called multiple times it overwrites the previous set of stored values 3617 and does not allocated additional space. 3618 3619 .seealso: MatRetrieveValues() 3620 3621 @*/ 3622 PetscErrorCode MatStoreValues(Mat mat) 3623 { 3624 PetscErrorCode ierr; 3625 3626 PetscFunctionBegin; 3627 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3628 if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 3629 if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3630 ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr); 3631 PetscFunctionReturn(0); 3632 } 3633 3634 PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat) 3635 { 3636 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3637 PetscErrorCode ierr; 3638 PetscInt nz = aij->i[mat->rmap->n]; 3639 3640 PetscFunctionBegin; 3641 if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3642 if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first"); 3643 /* copy values over */ 3644 ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr); 3645 PetscFunctionReturn(0); 3646 } 3647 3648 /*@ 3649 MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 3650 example, reuse of the linear part of a Jacobian, while recomputing the 3651 nonlinear portion. 3652 3653 Collect on Mat 3654 3655 Input Parameters: 3656 . mat - the matrix (currently only AIJ matrices support this option) 3657 3658 Level: advanced 3659 3660 .seealso: MatStoreValues() 3661 3662 @*/ 3663 PetscErrorCode MatRetrieveValues(Mat mat) 3664 { 3665 PetscErrorCode ierr; 3666 3667 PetscFunctionBegin; 3668 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3669 if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 3670 if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3671 ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr); 3672 PetscFunctionReturn(0); 3673 } 3674 3675 3676 /* --------------------------------------------------------------------------------*/ 3677 /*@C 3678 MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format 3679 (the default parallel PETSc format). For good matrix assembly performance 3680 the user should preallocate the matrix storage by setting the parameter nz 3681 (or the array nnz). By setting these parameters accurately, performance 3682 during matrix assembly can be increased by more than a factor of 50. 3683 3684 Collective 3685 3686 Input Parameters: 3687 + comm - MPI communicator, set to PETSC_COMM_SELF 3688 . m - number of rows 3689 . n - number of columns 3690 . nz - number of nonzeros per row (same for all rows) 3691 - nnz - array containing the number of nonzeros in the various rows 3692 (possibly different for each row) or NULL 3693 3694 Output Parameter: 3695 . A - the matrix 3696 3697 It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 3698 MatXXXXSetPreallocation() paradigm instead of this routine directly. 3699 [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 3700 3701 Notes: 3702 If nnz is given then nz is ignored 3703 3704 The AIJ format (also called the Yale sparse matrix format or 3705 compressed row storage), is fully compatible with standard Fortran 77 3706 storage. That is, the stored row and column indices can begin at 3707 either one (as in Fortran) or zero. See the users' manual for details. 3708 3709 Specify the preallocated storage with either nz or nnz (not both). 3710 Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 3711 allocation. For large problems you MUST preallocate memory or you 3712 will get TERRIBLE performance, see the users' manual chapter on matrices. 3713 3714 By default, this format uses inodes (identical nodes) when possible, to 3715 improve numerical efficiency of matrix-vector products and solves. We 3716 search for consecutive rows with the same nonzero structure, thereby 3717 reusing matrix information to achieve increased efficiency. 3718 3719 Options Database Keys: 3720 + -mat_no_inode - Do not use inodes 3721 - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3722 3723 Level: intermediate 3724 3725 .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays() 3726 3727 @*/ 3728 PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A) 3729 { 3730 PetscErrorCode ierr; 3731 3732 PetscFunctionBegin; 3733 ierr = MatCreate(comm,A);CHKERRQ(ierr); 3734 ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr); 3735 ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr); 3736 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr); 3737 PetscFunctionReturn(0); 3738 } 3739 3740 /*@C 3741 MatSeqAIJSetPreallocation - For good matrix assembly performance 3742 the user should preallocate the matrix storage by setting the parameter nz 3743 (or the array nnz). By setting these parameters accurately, performance 3744 during matrix assembly can be increased by more than a factor of 50. 3745 3746 Collective 3747 3748 Input Parameters: 3749 + B - The matrix 3750 . nz - number of nonzeros per row (same for all rows) 3751 - nnz - array containing the number of nonzeros in the various rows 3752 (possibly different for each row) or NULL 3753 3754 Notes: 3755 If nnz is given then nz is ignored 3756 3757 The AIJ format (also called the Yale sparse matrix format or 3758 compressed row storage), is fully compatible with standard Fortran 77 3759 storage. That is, the stored row and column indices can begin at 3760 either one (as in Fortran) or zero. See the users' manual for details. 3761 3762 Specify the preallocated storage with either nz or nnz (not both). 3763 Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 3764 allocation. For large problems you MUST preallocate memory or you 3765 will get TERRIBLE performance, see the users' manual chapter on matrices. 3766 3767 You can call MatGetInfo() to get information on how effective the preallocation was; 3768 for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 3769 You can also run with the option -info and look for messages with the string 3770 malloc in them to see if additional memory allocation was needed. 3771 3772 Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix 3773 entries or columns indices 3774 3775 By default, this format uses inodes (identical nodes) when possible, to 3776 improve numerical efficiency of matrix-vector products and solves. We 3777 search for consecutive rows with the same nonzero structure, thereby 3778 reusing matrix information to achieve increased efficiency. 3779 3780 Options Database Keys: 3781 + -mat_no_inode - Do not use inodes 3782 - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3783 3784 Level: intermediate 3785 3786 .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo() 3787 3788 @*/ 3789 PetscErrorCode MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[]) 3790 { 3791 PetscErrorCode ierr; 3792 3793 PetscFunctionBegin; 3794 PetscValidHeaderSpecific(B,MAT_CLASSID,1); 3795 PetscValidType(B,1); 3796 ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr); 3797 PetscFunctionReturn(0); 3798 } 3799 3800 PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz) 3801 { 3802 Mat_SeqAIJ *b; 3803 PetscBool skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE; 3804 PetscErrorCode ierr; 3805 PetscInt i; 3806 3807 PetscFunctionBegin; 3808 if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 3809 if (nz == MAT_SKIP_ALLOCATION) { 3810 skipallocation = PETSC_TRUE; 3811 nz = 0; 3812 } 3813 ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 3814 ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 3815 3816 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 3817 if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz); 3818 #if defined(PETSC_USE_DEBUG) 3819 if (nnz) { 3820 for (i=0; i<B->rmap->n; i++) { 3821 if (nnz[i] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %D value %D",i,nnz[i]); 3822 if (nnz[i] > B->cmap->n) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %D value %d rowlength %D",i,nnz[i],B->cmap->n); 3823 } 3824 } 3825 #endif 3826 3827 B->preallocated = PETSC_TRUE; 3828 3829 b = (Mat_SeqAIJ*)B->data; 3830 3831 if (!skipallocation) { 3832 if (!b->imax) { 3833 ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr); 3834 ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 3835 } 3836 if (!b->ilen) { 3837 /* b->ilen will count nonzeros in each row so far. */ 3838 ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr); 3839 ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 3840 } else { 3841 ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 3842 } 3843 if (!b->ipre) { 3844 ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr); 3845 ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 3846 } 3847 if (!nnz) { 3848 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 3849 else if (nz < 0) nz = 1; 3850 nz = PetscMin(nz,B->cmap->n); 3851 for (i=0; i<B->rmap->n; i++) b->imax[i] = nz; 3852 nz = nz*B->rmap->n; 3853 } else { 3854 nz = 0; 3855 for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz += nnz[i];} 3856 } 3857 3858 /* allocate the matrix space */ 3859 /* FIXME: should B's old memory be unlogged? */ 3860 ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr); 3861 if (B->structure_only) { 3862 ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr); 3863 ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr); 3864 ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr); 3865 } else { 3866 ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr); 3867 ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr); 3868 } 3869 b->i[0] = 0; 3870 for (i=1; i<B->rmap->n+1; i++) { 3871 b->i[i] = b->i[i-1] + b->imax[i-1]; 3872 } 3873 if (B->structure_only) { 3874 b->singlemalloc = PETSC_FALSE; 3875 b->free_a = PETSC_FALSE; 3876 } else { 3877 b->singlemalloc = PETSC_TRUE; 3878 b->free_a = PETSC_TRUE; 3879 } 3880 b->free_ij = PETSC_TRUE; 3881 } else { 3882 b->free_a = PETSC_FALSE; 3883 b->free_ij = PETSC_FALSE; 3884 } 3885 3886 if (b->ipre && nnz != b->ipre && b->imax) { 3887 /* reserve user-requested sparsity */ 3888 ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr); 3889 } 3890 3891 3892 b->nz = 0; 3893 b->maxnz = nz; 3894 B->info.nz_unneeded = (double)b->maxnz; 3895 if (realalloc) { 3896 ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 3897 } 3898 B->was_assembled = PETSC_FALSE; 3899 B->assembled = PETSC_FALSE; 3900 PetscFunctionReturn(0); 3901 } 3902 3903 3904 PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A) 3905 { 3906 Mat_SeqAIJ *a; 3907 PetscInt i; 3908 PetscErrorCode ierr; 3909 3910 PetscFunctionBegin; 3911 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 3912 3913 /* Check local size. If zero, then return */ 3914 if (!A->rmap->n) PetscFunctionReturn(0); 3915 3916 a = (Mat_SeqAIJ*)A->data; 3917 /* if no saved info, we error out */ 3918 if (!a->ipre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info \n"); 3919 3920 if (!a->i || !a->j || !a->a || !a->imax || !a->ilen) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Memory info is incomplete, and can not reset preallocation \n"); 3921 3922 ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr); 3923 ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr); 3924 a->i[0] = 0; 3925 for (i=1; i<A->rmap->n+1; i++) { 3926 a->i[i] = a->i[i-1] + a->imax[i-1]; 3927 } 3928 A->preallocated = PETSC_TRUE; 3929 a->nz = 0; 3930 a->maxnz = a->i[A->rmap->n]; 3931 A->info.nz_unneeded = (double)a->maxnz; 3932 A->was_assembled = PETSC_FALSE; 3933 A->assembled = PETSC_FALSE; 3934 PetscFunctionReturn(0); 3935 } 3936 3937 /*@ 3938 MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format. 3939 3940 Input Parameters: 3941 + B - the matrix 3942 . i - the indices into j for the start of each row (starts with zero) 3943 . j - the column indices for each row (starts with zero) these must be sorted for each row 3944 - v - optional values in the matrix 3945 3946 Level: developer 3947 3948 The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays() 3949 3950 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ 3951 @*/ 3952 PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[]) 3953 { 3954 PetscErrorCode ierr; 3955 3956 PetscFunctionBegin; 3957 PetscValidHeaderSpecific(B,MAT_CLASSID,1); 3958 PetscValidType(B,1); 3959 ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr); 3960 PetscFunctionReturn(0); 3961 } 3962 3963 PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[]) 3964 { 3965 PetscInt i; 3966 PetscInt m,n; 3967 PetscInt nz; 3968 PetscInt *nnz, nz_max = 0; 3969 PetscErrorCode ierr; 3970 3971 PetscFunctionBegin; 3972 if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]); 3973 3974 ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 3975 ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 3976 3977 ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr); 3978 ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr); 3979 for (i = 0; i < m; i++) { 3980 nz = Ii[i+1]- Ii[i]; 3981 nz_max = PetscMax(nz_max, nz); 3982 if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz); 3983 nnz[i] = nz; 3984 } 3985 ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr); 3986 ierr = PetscFree(nnz);CHKERRQ(ierr); 3987 3988 for (i = 0; i < m; i++) { 3989 ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr); 3990 } 3991 3992 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3993 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3994 3995 ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 3996 PetscFunctionReturn(0); 3997 } 3998 3999 #include <../src/mat/impls/dense/seq/dense.h> 4000 #include <petsc/private/kernels/petscaxpy.h> 4001 4002 /* 4003 Computes (B'*A')' since computing B*A directly is untenable 4004 4005 n p p 4006 ( ) ( ) ( ) 4007 m ( A ) * n ( B ) = m ( C ) 4008 ( ) ( ) ( ) 4009 4010 */ 4011 PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C) 4012 { 4013 PetscErrorCode ierr; 4014 Mat_SeqDense *sub_a = (Mat_SeqDense*)A->data; 4015 Mat_SeqAIJ *sub_b = (Mat_SeqAIJ*)B->data; 4016 Mat_SeqDense *sub_c = (Mat_SeqDense*)C->data; 4017 PetscInt i,n,m,q,p; 4018 const PetscInt *ii,*idx; 4019 const PetscScalar *b,*a,*a_q; 4020 PetscScalar *c,*c_q; 4021 4022 PetscFunctionBegin; 4023 m = A->rmap->n; 4024 n = A->cmap->n; 4025 p = B->cmap->n; 4026 a = sub_a->v; 4027 b = sub_b->a; 4028 c = sub_c->v; 4029 ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr); 4030 4031 ii = sub_b->i; 4032 idx = sub_b->j; 4033 for (i=0; i<n; i++) { 4034 q = ii[i+1] - ii[i]; 4035 while (q-->0) { 4036 c_q = c + m*(*idx); 4037 a_q = a + m*i; 4038 PetscKernelAXPY(c_q,*b,a_q,m); 4039 idx++; 4040 b++; 4041 } 4042 } 4043 PetscFunctionReturn(0); 4044 } 4045 4046 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat *C) 4047 { 4048 PetscErrorCode ierr; 4049 PetscInt m=A->rmap->n,n=B->cmap->n; 4050 Mat Cmat; 4051 4052 PetscFunctionBegin; 4053 if (A->cmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %D != B->rmap->n %D\n",A->cmap->n,B->rmap->n); 4054 ierr = MatCreate(PetscObjectComm((PetscObject)A),&Cmat);CHKERRQ(ierr); 4055 ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr); 4056 ierr = MatSetBlockSizesFromMats(Cmat,A,B);CHKERRQ(ierr); 4057 ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr); 4058 ierr = MatSeqDenseSetPreallocation(Cmat,NULL);CHKERRQ(ierr); 4059 4060 Cmat->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ; 4061 4062 *C = Cmat; 4063 PetscFunctionReturn(0); 4064 } 4065 4066 /* ----------------------------------------------------------------*/ 4067 PETSC_INTERN PetscErrorCode MatMatMult_SeqDense_SeqAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 4068 { 4069 PetscErrorCode ierr; 4070 4071 PetscFunctionBegin; 4072 if (scall == MAT_INITIAL_MATRIX) { 4073 ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 4074 ierr = MatMatMultSymbolic_SeqDense_SeqAIJ(A,B,fill,C);CHKERRQ(ierr); 4075 ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 4076 } 4077 ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 4078 ierr = MatMatMultNumeric_SeqDense_SeqAIJ(A,B,*C);CHKERRQ(ierr); 4079 ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 4080 PetscFunctionReturn(0); 4081 } 4082 4083 4084 /*MC 4085 MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 4086 based on compressed sparse row format. 4087 4088 Options Database Keys: 4089 . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 4090 4091 Level: beginner 4092 4093 .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType 4094 M*/ 4095 4096 /*MC 4097 MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 4098 4099 This matrix type is identical to MATSEQAIJ when constructed with a single process communicator, 4100 and MATMPIAIJ otherwise. As a result, for single process communicators, 4101 MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation is supported 4102 for communicators controlling multiple processes. It is recommended that you call both of 4103 the above preallocation routines for simplicity. 4104 4105 Options Database Keys: 4106 . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions() 4107 4108 Developer Notes: 4109 Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when 4110 enough exist. 4111 4112 Level: beginner 4113 4114 .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ 4115 M*/ 4116 4117 /*MC 4118 MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 4119 4120 This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator, 4121 and MATMPIAIJCRL otherwise. As a result, for single process communicators, 4122 MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 4123 for communicators controlling multiple processes. It is recommended that you call both of 4124 the above preallocation routines for simplicity. 4125 4126 Options Database Keys: 4127 . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions() 4128 4129 Level: beginner 4130 4131 .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL 4132 M*/ 4133 4134 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*); 4135 #if defined(PETSC_HAVE_ELEMENTAL) 4136 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*); 4137 #endif 4138 #if defined(PETSC_HAVE_HYPRE) 4139 PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*); 4140 PETSC_INTERN PetscErrorCode MatMatMatMult_Transpose_AIJ_AIJ(Mat,Mat,Mat,MatReuse,PetscReal,Mat*); 4141 #endif 4142 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat,MatType,MatReuse,Mat*); 4143 4144 PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*); 4145 PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*); 4146 PETSC_INTERN PetscErrorCode MatPtAP_IS_XAIJ(Mat,Mat,MatReuse,PetscReal,Mat*); 4147 4148 /*@C 4149 MatSeqAIJGetArray - gives access to the array where the data for a MATSEQAIJ matrix is stored 4150 4151 Not Collective 4152 4153 Input Parameter: 4154 . mat - a MATSEQAIJ matrix 4155 4156 Output Parameter: 4157 . array - pointer to the data 4158 4159 Level: intermediate 4160 4161 .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90() 4162 @*/ 4163 PetscErrorCode MatSeqAIJGetArray(Mat A,PetscScalar **array) 4164 { 4165 PetscErrorCode ierr; 4166 4167 PetscFunctionBegin; 4168 ierr = PetscUseMethod(A,"MatSeqAIJGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr); 4169 PetscFunctionReturn(0); 4170 } 4171 4172 /*@C 4173 MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row 4174 4175 Not Collective 4176 4177 Input Parameter: 4178 . mat - a MATSEQAIJ matrix 4179 4180 Output Parameter: 4181 . nz - the maximum number of nonzeros in any row 4182 4183 Level: intermediate 4184 4185 .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90() 4186 @*/ 4187 PetscErrorCode MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz) 4188 { 4189 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4190 4191 PetscFunctionBegin; 4192 *nz = aij->rmax; 4193 PetscFunctionReturn(0); 4194 } 4195 4196 /*@C 4197 MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray() 4198 4199 Not Collective 4200 4201 Input Parameters: 4202 + mat - a MATSEQAIJ matrix 4203 - array - pointer to the data 4204 4205 Level: intermediate 4206 4207 .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90() 4208 @*/ 4209 PetscErrorCode MatSeqAIJRestoreArray(Mat A,PetscScalar **array) 4210 { 4211 PetscErrorCode ierr; 4212 4213 PetscFunctionBegin; 4214 ierr = PetscUseMethod(A,"MatSeqAIJRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr); 4215 PetscFunctionReturn(0); 4216 } 4217 4218 #if defined(PETSC_HAVE_CUDA) 4219 PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat); 4220 #endif 4221 4222 PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B) 4223 { 4224 Mat_SeqAIJ *b; 4225 PetscErrorCode ierr; 4226 PetscMPIInt size; 4227 4228 PetscFunctionBegin; 4229 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr); 4230 if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1"); 4231 4232 ierr = PetscNewLog(B,&b);CHKERRQ(ierr); 4233 4234 B->data = (void*)b; 4235 4236 ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 4237 if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 4238 4239 b->row = 0; 4240 b->col = 0; 4241 b->icol = 0; 4242 b->reallocs = 0; 4243 b->ignorezeroentries = PETSC_FALSE; 4244 b->roworiented = PETSC_TRUE; 4245 b->nonew = 0; 4246 b->diag = 0; 4247 b->solve_work = 0; 4248 B->spptr = 0; 4249 b->saved_values = 0; 4250 b->idiag = 0; 4251 b->mdiag = 0; 4252 b->ssor_work = 0; 4253 b->omega = 1.0; 4254 b->fshift = 0.0; 4255 b->idiagvalid = PETSC_FALSE; 4256 b->ibdiagvalid = PETSC_FALSE; 4257 b->keepnonzeropattern = PETSC_FALSE; 4258 4259 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 4260 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJGetArray_C",MatSeqAIJGetArray_SeqAIJ);CHKERRQ(ierr); 4261 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJRestoreArray_C",MatSeqAIJRestoreArray_SeqAIJ);CHKERRQ(ierr); 4262 4263 #if defined(PETSC_HAVE_MATLAB_ENGINE) 4264 ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr); 4265 ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr); 4266 #endif 4267 4268 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr); 4269 ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr); 4270 ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr); 4271 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr); 4272 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr); 4273 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr); 4274 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr); 4275 #if defined(PETSC_HAVE_MKL_SPARSE) 4276 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr); 4277 #endif 4278 #if defined(PETSC_HAVE_CUDA) 4279 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr); 4280 #endif 4281 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr); 4282 #if defined(PETSC_HAVE_ELEMENTAL) 4283 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr); 4284 #endif 4285 #if defined(PETSC_HAVE_HYPRE) 4286 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr); 4287 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMatMult_transpose_seqaij_seqaij_C",MatMatMatMult_Transpose_AIJ_AIJ);CHKERRQ(ierr); 4288 #endif 4289 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr); 4290 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr); 4291 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr); 4292 ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr); 4293 ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr); 4294 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr); 4295 ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr); 4296 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr); 4297 ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr); 4298 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqdense_seqaij_C",MatMatMult_SeqDense_SeqAIJ);CHKERRQ(ierr); 4299 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaij_C",MatMatMultSymbolic_SeqDense_SeqAIJ);CHKERRQ(ierr); 4300 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqdense_seqaij_C",MatMatMultNumeric_SeqDense_SeqAIJ);CHKERRQ(ierr); 4301 ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_is_seqaij_C",MatPtAP_IS_XAIJ);CHKERRQ(ierr); 4302 ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr); 4303 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 4304 ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr); /* this allows changing the matrix subtype to say MATSEQAIJPERM */ 4305 PetscFunctionReturn(0); 4306 } 4307 4308 /* 4309 Given a matrix generated with MatGetFactor() duplicates all the information in A into B 4310 */ 4311 PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace) 4312 { 4313 Mat_SeqAIJ *c,*a = (Mat_SeqAIJ*)A->data; 4314 PetscErrorCode ierr; 4315 PetscInt m = A->rmap->n,i; 4316 4317 PetscFunctionBegin; 4318 c = (Mat_SeqAIJ*)C->data; 4319 4320 C->factortype = A->factortype; 4321 c->row = 0; 4322 c->col = 0; 4323 c->icol = 0; 4324 c->reallocs = 0; 4325 4326 C->assembled = PETSC_TRUE; 4327 4328 ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr); 4329 ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr); 4330 4331 ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr); 4332 ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr); 4333 ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr); 4334 ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr); 4335 ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr); 4336 4337 /* allocate the matrix space */ 4338 if (mallocmatspace) { 4339 ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr); 4340 ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 4341 4342 c->singlemalloc = PETSC_TRUE; 4343 4344 ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr); 4345 if (m > 0) { 4346 ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr); 4347 if (cpvalues == MAT_COPY_VALUES) { 4348 ierr = PetscArraycpy(c->a,a->a,a->i[m]);CHKERRQ(ierr); 4349 } else { 4350 ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr); 4351 } 4352 } 4353 } 4354 4355 c->ignorezeroentries = a->ignorezeroentries; 4356 c->roworiented = a->roworiented; 4357 c->nonew = a->nonew; 4358 if (a->diag) { 4359 ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr); 4360 ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr); 4361 ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 4362 } else c->diag = NULL; 4363 4364 c->solve_work = 0; 4365 c->saved_values = 0; 4366 c->idiag = 0; 4367 c->ssor_work = 0; 4368 c->keepnonzeropattern = a->keepnonzeropattern; 4369 c->free_a = PETSC_TRUE; 4370 c->free_ij = PETSC_TRUE; 4371 4372 c->rmax = a->rmax; 4373 c->nz = a->nz; 4374 c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 4375 C->preallocated = PETSC_TRUE; 4376 4377 c->compressedrow.use = a->compressedrow.use; 4378 c->compressedrow.nrows = a->compressedrow.nrows; 4379 if (a->compressedrow.use) { 4380 i = a->compressedrow.nrows; 4381 ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr); 4382 ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr); 4383 ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr); 4384 } else { 4385 c->compressedrow.use = PETSC_FALSE; 4386 c->compressedrow.i = NULL; 4387 c->compressedrow.rindex = NULL; 4388 } 4389 c->nonzerorowcnt = a->nonzerorowcnt; 4390 C->nonzerostate = A->nonzerostate; 4391 4392 ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr); 4393 ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr); 4394 PetscFunctionReturn(0); 4395 } 4396 4397 PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B) 4398 { 4399 PetscErrorCode ierr; 4400 4401 PetscFunctionBegin; 4402 ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr); 4403 ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr); 4404 if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) { 4405 ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr); 4406 } 4407 ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr); 4408 ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr); 4409 PetscFunctionReturn(0); 4410 } 4411 4412 PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer) 4413 { 4414 PetscBool isbinary, ishdf5; 4415 PetscErrorCode ierr; 4416 4417 PetscFunctionBegin; 4418 PetscValidHeaderSpecific(newMat,MAT_CLASSID,1); 4419 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 4420 /* force binary viewer to load .info file if it has not yet done so */ 4421 ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr); 4422 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 4423 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 4424 if (isbinary) { 4425 ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr); 4426 } else if (ishdf5) { 4427 #if defined(PETSC_HAVE_HDF5) 4428 ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr); 4429 #else 4430 SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 4431 #endif 4432 } else { 4433 SETERRQ2(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"Viewer type %s not yet supported for reading %s matrices",((PetscObject)viewer)->type_name,((PetscObject)newMat)->type_name); 4434 } 4435 PetscFunctionReturn(0); 4436 } 4437 4438 PetscErrorCode MatLoad_SeqAIJ_Binary(Mat newMat, PetscViewer viewer) 4439 { 4440 Mat_SeqAIJ *a; 4441 PetscErrorCode ierr; 4442 PetscInt i,sum,nz,header[4],*rowlengths = 0,M,N,rows,cols; 4443 int fd; 4444 PetscMPIInt size; 4445 MPI_Comm comm; 4446 PetscInt bs = newMat->rmap->bs; 4447 4448 PetscFunctionBegin; 4449 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 4450 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 4451 if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"view must have one processor"); 4452 4453 ierr = PetscOptionsBegin(comm,NULL,"Options for loading SEQAIJ matrix","Mat");CHKERRQ(ierr); 4454 ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,NULL);CHKERRQ(ierr); 4455 ierr = PetscOptionsEnd();CHKERRQ(ierr); 4456 if (bs < 0) bs = 1; 4457 ierr = MatSetBlockSize(newMat,bs);CHKERRQ(ierr); 4458 4459 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 4460 ierr = PetscBinaryRead(fd,header,4,NULL,PETSC_INT);CHKERRQ(ierr); 4461 if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file"); 4462 M = header[1]; N = header[2]; nz = header[3]; 4463 4464 if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ"); 4465 4466 /* read in row lengths */ 4467 ierr = PetscMalloc1(M,&rowlengths);CHKERRQ(ierr); 4468 ierr = PetscBinaryRead(fd,rowlengths,M,NULL,PETSC_INT);CHKERRQ(ierr); 4469 4470 /* check if sum of rowlengths is same as nz */ 4471 for (i=0,sum=0; i< M; i++) sum +=rowlengths[i]; 4472 if (sum != nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Inconsistant matrix data in file. no-nonzeros = %dD, sum-row-lengths = %D\n",nz,sum); 4473 4474 /* set global size if not set already*/ 4475 if (newMat->rmap->n < 0 && newMat->rmap->N < 0 && newMat->cmap->n < 0 && newMat->cmap->N < 0) { 4476 ierr = MatSetSizes(newMat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 4477 } else { 4478 /* if sizes and type are already set, check if the matrix global sizes are correct */ 4479 ierr = MatGetSize(newMat,&rows,&cols);CHKERRQ(ierr); 4480 if (rows < 0 && cols < 0) { /* user might provide local size instead of global size */ 4481 ierr = MatGetLocalSize(newMat,&rows,&cols);CHKERRQ(ierr); 4482 } 4483 if (M != rows || N != cols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%D, %D) than the input matrix (%D, %D)",M,N,rows,cols); 4484 } 4485 ierr = MatSeqAIJSetPreallocation_SeqAIJ(newMat,0,rowlengths);CHKERRQ(ierr); 4486 a = (Mat_SeqAIJ*)newMat->data; 4487 4488 ierr = PetscBinaryRead(fd,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr); 4489 4490 /* read in nonzero values */ 4491 ierr = PetscBinaryRead(fd,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr); 4492 4493 /* set matrix "i" values */ 4494 a->i[0] = 0; 4495 for (i=1; i<= M; i++) { 4496 a->i[i] = a->i[i-1] + rowlengths[i-1]; 4497 a->ilen[i-1] = rowlengths[i-1]; 4498 } 4499 ierr = PetscFree(rowlengths);CHKERRQ(ierr); 4500 4501 ierr = MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4502 ierr = MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4503 PetscFunctionReturn(0); 4504 } 4505 4506 PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg) 4507 { 4508 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data; 4509 PetscErrorCode ierr; 4510 #if defined(PETSC_USE_COMPLEX) 4511 PetscInt k; 4512 #endif 4513 4514 PetscFunctionBegin; 4515 /* If the matrix dimensions are not equal,or no of nonzeros */ 4516 if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) { 4517 *flg = PETSC_FALSE; 4518 PetscFunctionReturn(0); 4519 } 4520 4521 /* if the a->i are the same */ 4522 ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr); 4523 if (!*flg) PetscFunctionReturn(0); 4524 4525 /* if a->j are the same */ 4526 ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr); 4527 if (!*flg) PetscFunctionReturn(0); 4528 4529 /* if a->a are the same */ 4530 #if defined(PETSC_USE_COMPLEX) 4531 for (k=0; k<a->nz; k++) { 4532 if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])) { 4533 *flg = PETSC_FALSE; 4534 PetscFunctionReturn(0); 4535 } 4536 } 4537 #else 4538 ierr = PetscArraycmp(a->a,b->a,a->nz,flg);CHKERRQ(ierr); 4539 #endif 4540 PetscFunctionReturn(0); 4541 } 4542 4543 /*@ 4544 MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format) 4545 provided by the user. 4546 4547 Collective 4548 4549 Input Parameters: 4550 + comm - must be an MPI communicator of size 1 4551 . m - number of rows 4552 . n - number of columns 4553 . i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 4554 . j - column indices 4555 - a - matrix values 4556 4557 Output Parameter: 4558 . mat - the matrix 4559 4560 Level: intermediate 4561 4562 Notes: 4563 The i, j, and a arrays are not copied by this routine, the user must free these arrays 4564 once the matrix is destroyed and not before 4565 4566 You cannot set new nonzero locations into this matrix, that will generate an error. 4567 4568 The i and j indices are 0 based 4569 4570 The format which is used for the sparse matrix input, is equivalent to a 4571 row-major ordering.. i.e for the following matrix, the input data expected is 4572 as shown 4573 4574 $ 1 0 0 4575 $ 2 0 3 4576 $ 4 5 6 4577 $ 4578 $ i = {0,1,3,6} [size = nrow+1 = 3+1] 4579 $ j = {0,0,2,0,1,2} [size = 6]; values must be sorted for each row 4580 $ v = {1,2,3,4,5,6} [size = 6] 4581 4582 4583 .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR() 4584 4585 @*/ 4586 PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat) 4587 { 4588 PetscErrorCode ierr; 4589 PetscInt ii; 4590 Mat_SeqAIJ *aij; 4591 #if defined(PETSC_USE_DEBUG) 4592 PetscInt jj; 4593 #endif 4594 4595 PetscFunctionBegin; 4596 if (m > 0 && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 4597 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 4598 ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr); 4599 /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */ 4600 ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr); 4601 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr); 4602 aij = (Mat_SeqAIJ*)(*mat)->data; 4603 ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr); 4604 ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr); 4605 4606 aij->i = i; 4607 aij->j = j; 4608 aij->a = a; 4609 aij->singlemalloc = PETSC_FALSE; 4610 aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 4611 aij->free_a = PETSC_FALSE; 4612 aij->free_ij = PETSC_FALSE; 4613 4614 for (ii=0; ii<m; ii++) { 4615 aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii]; 4616 #if defined(PETSC_USE_DEBUG) 4617 if (i[ii+1] - i[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %D length = %D",ii,i[ii+1] - i[ii]); 4618 for (jj=i[ii]+1; jj<i[ii+1]; jj++) { 4619 if (j[jj] < j[jj-1]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual column %D) in row %D is not sorted",jj-i[ii],j[jj],ii); 4620 if (j[jj] == j[jj-1]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual column %D) in row %D is identical to previous entry",jj-i[ii],j[jj],ii); 4621 } 4622 #endif 4623 } 4624 #if defined(PETSC_USE_DEBUG) 4625 for (ii=0; ii<aij->i[m]; ii++) { 4626 if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]); 4627 if (j[ii] > n - 1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %D index = %D",ii,j[ii]); 4628 } 4629 #endif 4630 4631 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4632 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4633 PetscFunctionReturn(0); 4634 } 4635 /*@C 4636 MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format) 4637 provided by the user. 4638 4639 Collective 4640 4641 Input Parameters: 4642 + comm - must be an MPI communicator of size 1 4643 . m - number of rows 4644 . n - number of columns 4645 . i - row indices 4646 . j - column indices 4647 . a - matrix values 4648 . nz - number of nonzeros 4649 - idx - 0 or 1 based 4650 4651 Output Parameter: 4652 . mat - the matrix 4653 4654 Level: intermediate 4655 4656 Notes: 4657 The i and j indices are 0 based 4658 4659 The format which is used for the sparse matrix input, is equivalent to a 4660 row-major ordering.. i.e for the following matrix, the input data expected is 4661 as shown: 4662 4663 1 0 0 4664 2 0 3 4665 4 5 6 4666 4667 i = {0,1,1,2,2,2} 4668 j = {0,0,2,0,1,2} 4669 v = {1,2,3,4,5,6} 4670 4671 4672 .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR() 4673 4674 @*/ 4675 PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx) 4676 { 4677 PetscErrorCode ierr; 4678 PetscInt ii, *nnz, one = 1,row,col; 4679 4680 4681 PetscFunctionBegin; 4682 ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr); 4683 for (ii = 0; ii < nz; ii++) { 4684 nnz[i[ii] - !!idx] += 1; 4685 } 4686 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 4687 ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr); 4688 ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr); 4689 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr); 4690 for (ii = 0; ii < nz; ii++) { 4691 if (idx) { 4692 row = i[ii] - 1; 4693 col = j[ii] - 1; 4694 } else { 4695 row = i[ii]; 4696 col = j[ii]; 4697 } 4698 ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr); 4699 } 4700 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4701 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4702 ierr = PetscFree(nnz);CHKERRQ(ierr); 4703 PetscFunctionReturn(0); 4704 } 4705 4706 PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A) 4707 { 4708 Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data; 4709 PetscErrorCode ierr; 4710 4711 PetscFunctionBegin; 4712 a->idiagvalid = PETSC_FALSE; 4713 a->ibdiagvalid = PETSC_FALSE; 4714 4715 ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr); 4716 PetscFunctionReturn(0); 4717 } 4718 4719 PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat) 4720 { 4721 PetscErrorCode ierr; 4722 PetscMPIInt size; 4723 4724 PetscFunctionBegin; 4725 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 4726 if (size == 1) { 4727 if (scall == MAT_INITIAL_MATRIX) { 4728 ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr); 4729 } else { 4730 ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 4731 } 4732 } else { 4733 ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr); 4734 } 4735 PetscFunctionReturn(0); 4736 } 4737 4738 /* 4739 Permute A into C's *local* index space using rowemb,colemb. 4740 The embedding are supposed to be injections and the above implies that the range of rowemb is a subset 4741 of [0,m), colemb is in [0,n). 4742 If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A. 4743 */ 4744 PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B) 4745 { 4746 /* If making this function public, change the error returned in this function away from _PLIB. */ 4747 PetscErrorCode ierr; 4748 Mat_SeqAIJ *Baij; 4749 PetscBool seqaij; 4750 PetscInt m,n,*nz,i,j,count; 4751 PetscScalar v; 4752 const PetscInt *rowindices,*colindices; 4753 4754 PetscFunctionBegin; 4755 if (!B) PetscFunctionReturn(0); 4756 /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */ 4757 ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr); 4758 if (!seqaij) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type"); 4759 if (rowemb) { 4760 ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr); 4761 if (m != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Row IS of size %D is incompatible with matrix row size %D",m,B->rmap->n); 4762 } else { 4763 if (C->rmap->n != B->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix"); 4764 } 4765 if (colemb) { 4766 ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr); 4767 if (n != B->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Diag col IS of size %D is incompatible with input matrix col size %D",n,B->cmap->n); 4768 } else { 4769 if (C->cmap->n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix"); 4770 } 4771 4772 Baij = (Mat_SeqAIJ*)(B->data); 4773 if (pattern == DIFFERENT_NONZERO_PATTERN) { 4774 ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr); 4775 for (i=0; i<B->rmap->n; i++) { 4776 nz[i] = Baij->i[i+1] - Baij->i[i]; 4777 } 4778 ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr); 4779 ierr = PetscFree(nz);CHKERRQ(ierr); 4780 } 4781 if (pattern == SUBSET_NONZERO_PATTERN) { 4782 ierr = MatZeroEntries(C);CHKERRQ(ierr); 4783 } 4784 count = 0; 4785 rowindices = NULL; 4786 colindices = NULL; 4787 if (rowemb) { 4788 ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr); 4789 } 4790 if (colemb) { 4791 ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr); 4792 } 4793 for (i=0; i<B->rmap->n; i++) { 4794 PetscInt row; 4795 row = i; 4796 if (rowindices) row = rowindices[i]; 4797 for (j=Baij->i[i]; j<Baij->i[i+1]; j++) { 4798 PetscInt col; 4799 col = Baij->j[count]; 4800 if (colindices) col = colindices[col]; 4801 v = Baij->a[count]; 4802 ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr); 4803 ++count; 4804 } 4805 } 4806 /* FIXME: set C's nonzerostate correctly. */ 4807 /* Assembly for C is necessary. */ 4808 C->preallocated = PETSC_TRUE; 4809 C->assembled = PETSC_TRUE; 4810 C->was_assembled = PETSC_FALSE; 4811 PetscFunctionReturn(0); 4812 } 4813 4814 PetscFunctionList MatSeqAIJList = NULL; 4815 4816 /*@C 4817 MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype 4818 4819 Collective on Mat 4820 4821 Input Parameters: 4822 + mat - the matrix object 4823 - matype - matrix type 4824 4825 Options Database Key: 4826 . -mat_seqai_type <method> - for example seqaijcrl 4827 4828 4829 Level: intermediate 4830 4831 .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat 4832 @*/ 4833 PetscErrorCode MatSeqAIJSetType(Mat mat, MatType matype) 4834 { 4835 PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*); 4836 PetscBool sametype; 4837 4838 PetscFunctionBegin; 4839 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 4840 ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr); 4841 if (sametype) PetscFunctionReturn(0); 4842 4843 ierr = PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr); 4844 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype); 4845 ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr); 4846 PetscFunctionReturn(0); 4847 } 4848 4849 4850 /*@C 4851 MatSeqAIJRegister - - Adds a new sub-matrix type for sequential AIJ matrices 4852 4853 Not Collective 4854 4855 Input Parameters: 4856 + name - name of a new user-defined matrix type, for example MATSEQAIJCRL 4857 - function - routine to convert to subtype 4858 4859 Notes: 4860 MatSeqAIJRegister() may be called multiple times to add several user-defined solvers. 4861 4862 4863 Then, your matrix can be chosen with the procedural interface at runtime via the option 4864 $ -mat_seqaij_type my_mat 4865 4866 Level: advanced 4867 4868 .seealso: MatSeqAIJRegisterAll() 4869 4870 4871 Level: advanced 4872 @*/ 4873 PetscErrorCode MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *)) 4874 { 4875 PetscErrorCode ierr; 4876 4877 PetscFunctionBegin; 4878 ierr = MatInitializePackage();CHKERRQ(ierr); 4879 ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr); 4880 PetscFunctionReturn(0); 4881 } 4882 4883 PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE; 4884 4885 /*@C 4886 MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ 4887 4888 Not Collective 4889 4890 Level: advanced 4891 4892 Developers Note: CUSP and CUSPARSE do not yet support the MatConvert_SeqAIJ..() paradigm and thus cannot be registered here 4893 4894 .seealso: MatRegisterAll(), MatSeqAIJRegister() 4895 @*/ 4896 PetscErrorCode MatSeqAIJRegisterAll(void) 4897 { 4898 PetscErrorCode ierr; 4899 4900 PetscFunctionBegin; 4901 if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0); 4902 MatSeqAIJRegisterAllCalled = PETSC_TRUE; 4903 4904 ierr = MatSeqAIJRegister(MATSEQAIJCRL, MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr); 4905 ierr = MatSeqAIJRegister(MATSEQAIJPERM, MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr); 4906 ierr = MatSeqAIJRegister(MATSEQAIJSELL, MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr); 4907 #if defined(PETSC_HAVE_MKL_SPARSE) 4908 ierr = MatSeqAIJRegister(MATSEQAIJMKL, MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr); 4909 #endif 4910 #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA) 4911 ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr); 4912 #endif 4913 PetscFunctionReturn(0); 4914 } 4915 4916 /* 4917 Special version for direct calls from Fortran 4918 */ 4919 #include <petsc/private/fortranimpl.h> 4920 #if defined(PETSC_HAVE_FORTRAN_CAPS) 4921 #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ 4922 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 4923 #define matsetvaluesseqaij_ matsetvaluesseqaij 4924 #endif 4925 4926 /* Change these macros so can be used in void function */ 4927 #undef CHKERRQ 4928 #define CHKERRQ(ierr) CHKERRABORT(PetscObjectComm((PetscObject)A),ierr) 4929 #undef SETERRQ2 4930 #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr) 4931 #undef SETERRQ3 4932 #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr) 4933 4934 PETSC_EXTERN void PETSC_STDCALL matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr) 4935 { 4936 Mat A = *AA; 4937 PetscInt m = *mm, n = *nn; 4938 InsertMode is = *isis; 4939 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 4940 PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N; 4941 PetscInt *imax,*ai,*ailen; 4942 PetscErrorCode ierr; 4943 PetscInt *aj,nonew = a->nonew,lastcol = -1; 4944 MatScalar *ap,value,*aa; 4945 PetscBool ignorezeroentries = a->ignorezeroentries; 4946 PetscBool roworiented = a->roworiented; 4947 4948 PetscFunctionBegin; 4949 MatCheckPreallocated(A,1); 4950 imax = a->imax; 4951 ai = a->i; 4952 ailen = a->ilen; 4953 aj = a->j; 4954 aa = a->a; 4955 4956 for (k=0; k<m; k++) { /* loop over added rows */ 4957 row = im[k]; 4958 if (row < 0) continue; 4959 #if defined(PETSC_USE_DEBUG) 4960 if (row >= A->rmap->n) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large"); 4961 #endif 4962 rp = aj + ai[row]; ap = aa + ai[row]; 4963 rmax = imax[row]; nrow = ailen[row]; 4964 low = 0; 4965 high = nrow; 4966 for (l=0; l<n; l++) { /* loop over added columns */ 4967 if (in[l] < 0) continue; 4968 #if defined(PETSC_USE_DEBUG) 4969 if (in[l] >= A->cmap->n) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large"); 4970 #endif 4971 col = in[l]; 4972 if (roworiented) value = v[l + k*n]; 4973 else value = v[k + l*m]; 4974 4975 if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 4976 4977 if (col <= lastcol) low = 0; 4978 else high = nrow; 4979 lastcol = col; 4980 while (high-low > 5) { 4981 t = (low+high)/2; 4982 if (rp[t] > col) high = t; 4983 else low = t; 4984 } 4985 for (i=low; i<high; i++) { 4986 if (rp[i] > col) break; 4987 if (rp[i] == col) { 4988 if (is == ADD_VALUES) ap[i] += value; 4989 else ap[i] = value; 4990 goto noinsert; 4991 } 4992 } 4993 if (value == 0.0 && ignorezeroentries) goto noinsert; 4994 if (nonew == 1) goto noinsert; 4995 if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix"); 4996 MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar); 4997 N = nrow++ - 1; a->nz++; high++; 4998 /* shift up all the later entries in this row */ 4999 for (ii=N; ii>=i; ii--) { 5000 rp[ii+1] = rp[ii]; 5001 ap[ii+1] = ap[ii]; 5002 } 5003 rp[i] = col; 5004 ap[i] = value; 5005 A->nonzerostate++; 5006 noinsert:; 5007 low = i + 1; 5008 } 5009 ailen[row] = nrow; 5010 } 5011 PetscFunctionReturnVoid(); 5012 } 5013