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