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