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