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 #undef __FUNCT__ 1107 #define __FUNCT__ "MatDestroy_SeqAIJ" 1108 PetscErrorCode MatDestroy_SeqAIJ(Mat A) 1109 { 1110 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1111 PetscErrorCode ierr; 1112 1113 PetscFunctionBegin; 1114 #if defined(PETSC_USE_LOG) 1115 PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz); 1116 #endif 1117 ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr); 1118 ierr = ISDestroy(&a->row);CHKERRQ(ierr); 1119 ierr = ISDestroy(&a->col);CHKERRQ(ierr); 1120 ierr = PetscFree(a->diag);CHKERRQ(ierr); 1121 ierr = PetscFree(a->ibdiag);CHKERRQ(ierr); 1122 ierr = PetscFree2(a->imax,a->ilen);CHKERRQ(ierr); 1123 ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr); 1124 ierr = PetscFree(a->solve_work);CHKERRQ(ierr); 1125 ierr = ISDestroy(&a->icol);CHKERRQ(ierr); 1126 ierr = PetscFree(a->saved_values);CHKERRQ(ierr); 1127 ierr = ISColoringDestroy(&a->coloring);CHKERRQ(ierr); 1128 ierr = PetscFree(a->xtoy);CHKERRQ(ierr); 1129 ierr = MatDestroy(&a->XtoY);CHKERRQ(ierr); 1130 ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr); 1131 ierr = PetscFree(a->matmult_abdense);CHKERRQ(ierr); 1132 1133 ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr); 1134 ierr = PetscFree(A->data);CHKERRQ(ierr); 1135 1136 ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 1137 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr); 1138 ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr); 1139 ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr); 1140 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr); 1141 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr); 1142 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr); 1143 #if defined(PETSC_HAVE_ELEMENTAL) 1144 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr); 1145 #endif 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_SeqX_private" 2802 PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz) 2803 { 2804 PetscInt i,j,k,nzx,nzy; 2805 2806 PetscFunctionBegin; 2807 /* Set the number of nonzeros in the new matrix */ 2808 for (i=0; i<m; i++) { 2809 const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i]; 2810 nzx = xi[i+1] - xi[i]; 2811 nzy = yi[i+1] - yi[i]; 2812 nnz[i] = 0; 2813 for (j=0,k=0; j<nzx; j++) { /* Point in X */ 2814 for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */ 2815 if (k<nzy && yjj[k]==xjj[j]) k++; /* Skip duplicate */ 2816 nnz[i]++; 2817 } 2818 for (; k<nzy; k++) nnz[i]++; 2819 } 2820 PetscFunctionReturn(0); 2821 } 2822 2823 #undef __FUNCT__ 2824 #define __FUNCT__ "MatAXPYGetPreallocation_SeqAIJ" 2825 PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz) 2826 { 2827 PetscInt m = Y->rmap->N; 2828 Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data; 2829 Mat_SeqAIJ *y = (Mat_SeqAIJ*)Y->data; 2830 PetscErrorCode ierr; 2831 2832 PetscFunctionBegin; 2833 /* Set the number of nonzeros in the new matrix */ 2834 ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr); 2835 PetscFunctionReturn(0); 2836 } 2837 2838 #undef __FUNCT__ 2839 #define __FUNCT__ "MatAXPY_SeqAIJ" 2840 PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str) 2841 { 2842 PetscErrorCode ierr; 2843 PetscInt i; 2844 Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data; 2845 PetscBLASInt one=1,bnz; 2846 2847 PetscFunctionBegin; 2848 ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr); 2849 if (str == SAME_NONZERO_PATTERN) { 2850 PetscScalar alpha = a; 2851 PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one)); 2852 ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr); 2853 ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr); 2854 } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 2855 if (y->xtoy && y->XtoY != X) { 2856 ierr = PetscFree(y->xtoy);CHKERRQ(ierr); 2857 ierr = MatDestroy(&y->XtoY);CHKERRQ(ierr); 2858 } 2859 if (!y->xtoy) { /* get xtoy */ 2860 ierr = MatAXPYGetxtoy_Private(X->rmap->n,x->i,x->j,NULL, y->i,y->j,NULL, &y->xtoy);CHKERRQ(ierr); 2861 y->XtoY = X; 2862 ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 2863 } 2864 for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += a*(x->a[i]); 2865 ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr); 2866 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); 2867 } else { 2868 Mat B; 2869 PetscInt *nnz; 2870 ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr); 2871 ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr); 2872 ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr); 2873 ierr = MatSetSizes(B,Y->rmap->n,Y->cmap->n,Y->rmap->N,Y->cmap->N);CHKERRQ(ierr); 2874 ierr = MatSetBlockSizesFromMats(B,Y,Y);CHKERRQ(ierr); 2875 ierr = MatSetType(B,(MatType) ((PetscObject)Y)->type_name);CHKERRQ(ierr); 2876 ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr); 2877 ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr); 2878 ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr); 2879 ierr = MatHeaderReplace(Y,B);CHKERRQ(ierr); 2880 ierr = PetscFree(nnz);CHKERRQ(ierr); 2881 } 2882 PetscFunctionReturn(0); 2883 } 2884 2885 #undef __FUNCT__ 2886 #define __FUNCT__ "MatConjugate_SeqAIJ" 2887 PetscErrorCode MatConjugate_SeqAIJ(Mat mat) 2888 { 2889 #if defined(PETSC_USE_COMPLEX) 2890 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 2891 PetscInt i,nz; 2892 PetscScalar *a; 2893 2894 PetscFunctionBegin; 2895 nz = aij->nz; 2896 a = aij->a; 2897 for (i=0; i<nz; i++) a[i] = PetscConj(a[i]); 2898 #else 2899 PetscFunctionBegin; 2900 #endif 2901 PetscFunctionReturn(0); 2902 } 2903 2904 #undef __FUNCT__ 2905 #define __FUNCT__ "MatGetRowMaxAbs_SeqAIJ" 2906 PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2907 { 2908 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2909 PetscErrorCode ierr; 2910 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2911 PetscReal atmp; 2912 PetscScalar *x; 2913 MatScalar *aa; 2914 2915 PetscFunctionBegin; 2916 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2917 aa = a->a; 2918 ai = a->i; 2919 aj = a->j; 2920 2921 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2922 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2923 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 2924 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2925 for (i=0; i<m; i++) { 2926 ncols = ai[1] - ai[0]; ai++; 2927 x[i] = 0.0; 2928 for (j=0; j<ncols; j++) { 2929 atmp = PetscAbsScalar(*aa); 2930 if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;} 2931 aa++; aj++; 2932 } 2933 } 2934 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2935 PetscFunctionReturn(0); 2936 } 2937 2938 #undef __FUNCT__ 2939 #define __FUNCT__ "MatGetRowMax_SeqAIJ" 2940 PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2941 { 2942 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2943 PetscErrorCode ierr; 2944 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2945 PetscScalar *x; 2946 MatScalar *aa; 2947 2948 PetscFunctionBegin; 2949 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2950 aa = a->a; 2951 ai = a->i; 2952 aj = a->j; 2953 2954 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2955 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2956 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 2957 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2958 for (i=0; i<m; i++) { 2959 ncols = ai[1] - ai[0]; ai++; 2960 if (ncols == A->cmap->n) { /* row is dense */ 2961 x[i] = *aa; if (idx) idx[i] = 0; 2962 } else { /* row is sparse so already KNOW maximum is 0.0 or higher */ 2963 x[i] = 0.0; 2964 if (idx) { 2965 idx[i] = 0; /* in case ncols is zero */ 2966 for (j=0;j<ncols;j++) { /* find first implicit 0.0 in the row */ 2967 if (aj[j] > j) { 2968 idx[i] = j; 2969 break; 2970 } 2971 } 2972 } 2973 } 2974 for (j=0; j<ncols; j++) { 2975 if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 2976 aa++; aj++; 2977 } 2978 } 2979 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2980 PetscFunctionReturn(0); 2981 } 2982 2983 #undef __FUNCT__ 2984 #define __FUNCT__ "MatGetRowMinAbs_SeqAIJ" 2985 PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2986 { 2987 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2988 PetscErrorCode ierr; 2989 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2990 PetscReal atmp; 2991 PetscScalar *x; 2992 MatScalar *aa; 2993 2994 PetscFunctionBegin; 2995 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2996 aa = a->a; 2997 ai = a->i; 2998 aj = a->j; 2999 3000 ierr = VecSet(v,0.0);CHKERRQ(ierr); 3001 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 3002 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 3003 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); 3004 for (i=0; i<m; i++) { 3005 ncols = ai[1] - ai[0]; ai++; 3006 if (ncols) { 3007 /* Get first nonzero */ 3008 for (j = 0; j < ncols; j++) { 3009 atmp = PetscAbsScalar(aa[j]); 3010 if (atmp > 1.0e-12) { 3011 x[i] = atmp; 3012 if (idx) idx[i] = aj[j]; 3013 break; 3014 } 3015 } 3016 if (j == ncols) {x[i] = PetscAbsScalar(*aa); if (idx) idx[i] = *aj;} 3017 } else { 3018 x[i] = 0.0; if (idx) idx[i] = 0; 3019 } 3020 for (j = 0; j < ncols; j++) { 3021 atmp = PetscAbsScalar(*aa); 3022 if (atmp > 1.0e-12 && PetscAbsScalar(x[i]) > atmp) {x[i] = atmp; if (idx) idx[i] = *aj;} 3023 aa++; aj++; 3024 } 3025 } 3026 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 3027 PetscFunctionReturn(0); 3028 } 3029 3030 #undef __FUNCT__ 3031 #define __FUNCT__ "MatGetRowMin_SeqAIJ" 3032 PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3033 { 3034 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3035 PetscErrorCode ierr; 3036 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 3037 PetscScalar *x; 3038 MatScalar *aa; 3039 3040 PetscFunctionBegin; 3041 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3042 aa = a->a; 3043 ai = a->i; 3044 aj = a->j; 3045 3046 ierr = VecSet(v,0.0);CHKERRQ(ierr); 3047 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 3048 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 3049 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 3050 for (i=0; i<m; i++) { 3051 ncols = ai[1] - ai[0]; ai++; 3052 if (ncols == A->cmap->n) { /* row is dense */ 3053 x[i] = *aa; if (idx) idx[i] = 0; 3054 } else { /* row is sparse so already KNOW minimum is 0.0 or lower */ 3055 x[i] = 0.0; 3056 if (idx) { /* find first implicit 0.0 in the row */ 3057 idx[i] = 0; /* in case ncols is zero */ 3058 for (j=0; j<ncols; j++) { 3059 if (aj[j] > j) { 3060 idx[i] = j; 3061 break; 3062 } 3063 } 3064 } 3065 } 3066 for (j=0; j<ncols; j++) { 3067 if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 3068 aa++; aj++; 3069 } 3070 } 3071 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 3072 PetscFunctionReturn(0); 3073 } 3074 3075 #include <petscblaslapack.h> 3076 #include <petsc-private/kernels/blockinvert.h> 3077 3078 #undef __FUNCT__ 3079 #define __FUNCT__ "MatInvertBlockDiagonal_SeqAIJ" 3080 PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values) 3081 { 3082 Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 3083 PetscErrorCode ierr; 3084 PetscInt i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j; 3085 MatScalar *diag,work[25],*v_work; 3086 PetscReal shift = 0.0; 3087 3088 PetscFunctionBegin; 3089 if (a->ibdiagvalid) { 3090 if (values) *values = a->ibdiag; 3091 PetscFunctionReturn(0); 3092 } 3093 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 3094 if (!a->ibdiag) { 3095 ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr); 3096 ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr); 3097 } 3098 diag = a->ibdiag; 3099 if (values) *values = a->ibdiag; 3100 /* factor and invert each block */ 3101 switch (bs) { 3102 case 1: 3103 for (i=0; i<mbs; i++) { 3104 ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr); 3105 diag[i] = (PetscScalar)1.0 / (diag[i] + shift); 3106 } 3107 break; 3108 case 2: 3109 for (i=0; i<mbs; i++) { 3110 ij[0] = 2*i; ij[1] = 2*i + 1; 3111 ierr = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr); 3112 ierr = PetscKernel_A_gets_inverse_A_2(diag,shift);CHKERRQ(ierr); 3113 ierr = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr); 3114 diag += 4; 3115 } 3116 break; 3117 case 3: 3118 for (i=0; i<mbs; i++) { 3119 ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2; 3120 ierr = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr); 3121 ierr = PetscKernel_A_gets_inverse_A_3(diag,shift);CHKERRQ(ierr); 3122 ierr = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr); 3123 diag += 9; 3124 } 3125 break; 3126 case 4: 3127 for (i=0; i<mbs; i++) { 3128 ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3; 3129 ierr = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr); 3130 ierr = PetscKernel_A_gets_inverse_A_4(diag,shift);CHKERRQ(ierr); 3131 ierr = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr); 3132 diag += 16; 3133 } 3134 break; 3135 case 5: 3136 for (i=0; i<mbs; i++) { 3137 ij[0] = 5*i; ij[1] = 5*i + 1; ij[2] = 5*i + 2; ij[3] = 5*i + 3; ij[4] = 5*i + 4; 3138 ierr = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr); 3139 ierr = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift);CHKERRQ(ierr); 3140 ierr = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr); 3141 diag += 25; 3142 } 3143 break; 3144 case 6: 3145 for (i=0; i<mbs; i++) { 3146 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; 3147 ierr = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr); 3148 ierr = PetscKernel_A_gets_inverse_A_6(diag,shift);CHKERRQ(ierr); 3149 ierr = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr); 3150 diag += 36; 3151 } 3152 break; 3153 case 7: 3154 for (i=0; i<mbs; i++) { 3155 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; 3156 ierr = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr); 3157 ierr = PetscKernel_A_gets_inverse_A_7(diag,shift);CHKERRQ(ierr); 3158 ierr = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr); 3159 diag += 49; 3160 } 3161 break; 3162 default: 3163 ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr); 3164 for (i=0; i<mbs; i++) { 3165 for (j=0; j<bs; j++) { 3166 IJ[j] = bs*i + j; 3167 } 3168 ierr = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr); 3169 ierr = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work);CHKERRQ(ierr); 3170 ierr = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr); 3171 diag += bs2; 3172 } 3173 ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr); 3174 } 3175 a->ibdiagvalid = PETSC_TRUE; 3176 PetscFunctionReturn(0); 3177 } 3178 3179 #undef __FUNCT__ 3180 #define __FUNCT__ "MatSetRandom_SeqAIJ" 3181 static PetscErrorCode MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx) 3182 { 3183 PetscErrorCode ierr; 3184 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)x->data; 3185 PetscScalar a; 3186 PetscInt m,n,i,j,col; 3187 3188 PetscFunctionBegin; 3189 if (!x->assembled) { 3190 ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr); 3191 for (i=0; i<m; i++) { 3192 for (j=0; j<aij->imax[i]; j++) { 3193 ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr); 3194 col = (PetscInt)(n*PetscRealPart(a)); 3195 ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr); 3196 } 3197 } 3198 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet coded"); 3199 ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3200 ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3201 PetscFunctionReturn(0); 3202 } 3203 3204 /* -------------------------------------------------------------------*/ 3205 static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ, 3206 MatGetRow_SeqAIJ, 3207 MatRestoreRow_SeqAIJ, 3208 MatMult_SeqAIJ, 3209 /* 4*/ MatMultAdd_SeqAIJ, 3210 MatMultTranspose_SeqAIJ, 3211 MatMultTransposeAdd_SeqAIJ, 3212 0, 3213 0, 3214 0, 3215 /* 10*/ 0, 3216 MatLUFactor_SeqAIJ, 3217 0, 3218 MatSOR_SeqAIJ, 3219 MatTranspose_SeqAIJ, 3220 /*1 5*/ MatGetInfo_SeqAIJ, 3221 MatEqual_SeqAIJ, 3222 MatGetDiagonal_SeqAIJ, 3223 MatDiagonalScale_SeqAIJ, 3224 MatNorm_SeqAIJ, 3225 /* 20*/ 0, 3226 MatAssemblyEnd_SeqAIJ, 3227 MatSetOption_SeqAIJ, 3228 MatZeroEntries_SeqAIJ, 3229 /* 24*/ MatZeroRows_SeqAIJ, 3230 0, 3231 0, 3232 0, 3233 0, 3234 /* 29*/ MatSetUp_SeqAIJ, 3235 0, 3236 0, 3237 0, 3238 0, 3239 /* 34*/ MatDuplicate_SeqAIJ, 3240 0, 3241 0, 3242 MatILUFactor_SeqAIJ, 3243 0, 3244 /* 39*/ MatAXPY_SeqAIJ, 3245 MatGetSubMatrices_SeqAIJ, 3246 MatIncreaseOverlap_SeqAIJ, 3247 MatGetValues_SeqAIJ, 3248 MatCopy_SeqAIJ, 3249 /* 44*/ MatGetRowMax_SeqAIJ, 3250 MatScale_SeqAIJ, 3251 0, 3252 MatDiagonalSet_SeqAIJ, 3253 MatZeroRowsColumns_SeqAIJ, 3254 /* 49*/ MatSetRandom_SeqAIJ, 3255 MatGetRowIJ_SeqAIJ, 3256 MatRestoreRowIJ_SeqAIJ, 3257 MatGetColumnIJ_SeqAIJ, 3258 MatRestoreColumnIJ_SeqAIJ, 3259 /* 54*/ MatFDColoringCreate_SeqXAIJ, 3260 0, 3261 0, 3262 MatPermute_SeqAIJ, 3263 0, 3264 /* 59*/ 0, 3265 MatDestroy_SeqAIJ, 3266 MatView_SeqAIJ, 3267 0, 3268 MatMatMatMult_SeqAIJ_SeqAIJ_SeqAIJ, 3269 /* 64*/ MatMatMatMultSymbolic_SeqAIJ_SeqAIJ_SeqAIJ, 3270 MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ, 3271 0, 3272 0, 3273 0, 3274 /* 69*/ MatGetRowMaxAbs_SeqAIJ, 3275 MatGetRowMinAbs_SeqAIJ, 3276 0, 3277 MatSetColoring_SeqAIJ, 3278 0, 3279 /* 74*/ MatSetValuesAdifor_SeqAIJ, 3280 MatFDColoringApply_AIJ, 3281 0, 3282 0, 3283 0, 3284 /* 79*/ MatFindZeroDiagonals_SeqAIJ, 3285 0, 3286 0, 3287 0, 3288 MatLoad_SeqAIJ, 3289 /* 84*/ MatIsSymmetric_SeqAIJ, 3290 MatIsHermitian_SeqAIJ, 3291 0, 3292 0, 3293 0, 3294 /* 89*/ MatMatMult_SeqAIJ_SeqAIJ, 3295 MatMatMultSymbolic_SeqAIJ_SeqAIJ, 3296 MatMatMultNumeric_SeqAIJ_SeqAIJ, 3297 MatPtAP_SeqAIJ_SeqAIJ, 3298 MatPtAPSymbolic_SeqAIJ_SeqAIJ_DenseAxpy, 3299 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ, 3300 MatMatTransposeMult_SeqAIJ_SeqAIJ, 3301 MatMatTransposeMultSymbolic_SeqAIJ_SeqAIJ, 3302 MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ, 3303 0, 3304 /* 99*/ 0, 3305 0, 3306 0, 3307 MatConjugate_SeqAIJ, 3308 0, 3309 /*104*/ MatSetValuesRow_SeqAIJ, 3310 MatRealPart_SeqAIJ, 3311 MatImaginaryPart_SeqAIJ, 3312 0, 3313 0, 3314 /*109*/ MatMatSolve_SeqAIJ, 3315 0, 3316 MatGetRowMin_SeqAIJ, 3317 0, 3318 MatMissingDiagonal_SeqAIJ, 3319 /*114*/ 0, 3320 0, 3321 0, 3322 0, 3323 0, 3324 /*119*/ 0, 3325 0, 3326 0, 3327 0, 3328 MatGetMultiProcBlock_SeqAIJ, 3329 /*124*/ MatFindNonzeroRows_SeqAIJ, 3330 MatGetColumnNorms_SeqAIJ, 3331 MatInvertBlockDiagonal_SeqAIJ, 3332 0, 3333 0, 3334 /*129*/ 0, 3335 MatTransposeMatMult_SeqAIJ_SeqAIJ, 3336 MatTransposeMatMultSymbolic_SeqAIJ_SeqAIJ, 3337 MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ, 3338 MatTransposeColoringCreate_SeqAIJ, 3339 /*134*/ MatTransColoringApplySpToDen_SeqAIJ, 3340 MatTransColoringApplyDenToSp_SeqAIJ, 3341 MatRARt_SeqAIJ_SeqAIJ, 3342 MatRARtSymbolic_SeqAIJ_SeqAIJ, 3343 MatRARtNumeric_SeqAIJ_SeqAIJ, 3344 /*139*/0, 3345 0, 3346 0, 3347 MatFDColoringSetUp_SeqXAIJ, 3348 MatFindOffBlockDiagonalEntries_SeqAIJ, 3349 /*144*/MatCreateMPIMatConcatenateSeqMat_SeqAIJ 3350 }; 3351 3352 #undef __FUNCT__ 3353 #define __FUNCT__ "MatSeqAIJSetColumnIndices_SeqAIJ" 3354 PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices) 3355 { 3356 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3357 PetscInt i,nz,n; 3358 3359 PetscFunctionBegin; 3360 nz = aij->maxnz; 3361 n = mat->rmap->n; 3362 for (i=0; i<nz; i++) { 3363 aij->j[i] = indices[i]; 3364 } 3365 aij->nz = nz; 3366 for (i=0; i<n; i++) { 3367 aij->ilen[i] = aij->imax[i]; 3368 } 3369 PetscFunctionReturn(0); 3370 } 3371 3372 #undef __FUNCT__ 3373 #define __FUNCT__ "MatSeqAIJSetColumnIndices" 3374 /*@ 3375 MatSeqAIJSetColumnIndices - Set the column indices for all the rows 3376 in the matrix. 3377 3378 Input Parameters: 3379 + mat - the SeqAIJ matrix 3380 - indices - the column indices 3381 3382 Level: advanced 3383 3384 Notes: 3385 This can be called if you have precomputed the nonzero structure of the 3386 matrix and want to provide it to the matrix object to improve the performance 3387 of the MatSetValues() operation. 3388 3389 You MUST have set the correct numbers of nonzeros per row in the call to 3390 MatCreateSeqAIJ(), and the columns indices MUST be sorted. 3391 3392 MUST be called before any calls to MatSetValues(); 3393 3394 The indices should start with zero, not one. 3395 3396 @*/ 3397 PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices) 3398 { 3399 PetscErrorCode ierr; 3400 3401 PetscFunctionBegin; 3402 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3403 PetscValidPointer(indices,2); 3404 ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr); 3405 PetscFunctionReturn(0); 3406 } 3407 3408 /* ----------------------------------------------------------------------------------------*/ 3409 3410 #undef __FUNCT__ 3411 #define __FUNCT__ "MatStoreValues_SeqAIJ" 3412 PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) 3413 { 3414 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3415 PetscErrorCode ierr; 3416 size_t nz = aij->i[mat->rmap->n]; 3417 3418 PetscFunctionBegin; 3419 if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3420 3421 /* allocate space for values if not already there */ 3422 if (!aij->saved_values) { 3423 ierr = PetscMalloc1((nz+1),&aij->saved_values);CHKERRQ(ierr); 3424 ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr); 3425 } 3426 3427 /* copy values over */ 3428 ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr); 3429 PetscFunctionReturn(0); 3430 } 3431 3432 #undef __FUNCT__ 3433 #define __FUNCT__ "MatStoreValues" 3434 /*@ 3435 MatStoreValues - Stashes a copy of the matrix values; this allows, for 3436 example, reuse of the linear part of a Jacobian, while recomputing the 3437 nonlinear portion. 3438 3439 Collect on Mat 3440 3441 Input Parameters: 3442 . mat - the matrix (currently only AIJ matrices support this option) 3443 3444 Level: advanced 3445 3446 Common Usage, with SNESSolve(): 3447 $ Create Jacobian matrix 3448 $ Set linear terms into matrix 3449 $ Apply boundary conditions to matrix, at this time matrix must have 3450 $ final nonzero structure (i.e. setting the nonlinear terms and applying 3451 $ boundary conditions again will not change the nonzero structure 3452 $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3453 $ ierr = MatStoreValues(mat); 3454 $ Call SNESSetJacobian() with matrix 3455 $ In your Jacobian routine 3456 $ ierr = MatRetrieveValues(mat); 3457 $ Set nonlinear terms in matrix 3458 3459 Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself: 3460 $ // build linear portion of Jacobian 3461 $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3462 $ ierr = MatStoreValues(mat); 3463 $ loop over nonlinear iterations 3464 $ ierr = MatRetrieveValues(mat); 3465 $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian 3466 $ // call MatAssemblyBegin/End() on matrix 3467 $ Solve linear system with Jacobian 3468 $ endloop 3469 3470 Notes: 3471 Matrix must already be assemblied before calling this routine 3472 Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before 3473 calling this routine. 3474 3475 When this is called multiple times it overwrites the previous set of stored values 3476 and does not allocated additional space. 3477 3478 .seealso: MatRetrieveValues() 3479 3480 @*/ 3481 PetscErrorCode MatStoreValues(Mat mat) 3482 { 3483 PetscErrorCode ierr; 3484 3485 PetscFunctionBegin; 3486 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3487 if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 3488 if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3489 ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr); 3490 PetscFunctionReturn(0); 3491 } 3492 3493 #undef __FUNCT__ 3494 #define __FUNCT__ "MatRetrieveValues_SeqAIJ" 3495 PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat) 3496 { 3497 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3498 PetscErrorCode ierr; 3499 PetscInt nz = aij->i[mat->rmap->n]; 3500 3501 PetscFunctionBegin; 3502 if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3503 if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first"); 3504 /* copy values over */ 3505 ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr); 3506 PetscFunctionReturn(0); 3507 } 3508 3509 #undef __FUNCT__ 3510 #define __FUNCT__ "MatRetrieveValues" 3511 /*@ 3512 MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 3513 example, reuse of the linear part of a Jacobian, while recomputing the 3514 nonlinear portion. 3515 3516 Collect on Mat 3517 3518 Input Parameters: 3519 . mat - the matrix (currently on AIJ matrices support this option) 3520 3521 Level: advanced 3522 3523 .seealso: MatStoreValues() 3524 3525 @*/ 3526 PetscErrorCode MatRetrieveValues(Mat mat) 3527 { 3528 PetscErrorCode ierr; 3529 3530 PetscFunctionBegin; 3531 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3532 if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 3533 if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3534 ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr); 3535 PetscFunctionReturn(0); 3536 } 3537 3538 3539 /* --------------------------------------------------------------------------------*/ 3540 #undef __FUNCT__ 3541 #define __FUNCT__ "MatCreateSeqAIJ" 3542 /*@C 3543 MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format 3544 (the default parallel PETSc format). For good matrix assembly performance 3545 the user should preallocate the matrix storage by setting the parameter nz 3546 (or the array nnz). By setting these parameters accurately, performance 3547 during matrix assembly can be increased by more than a factor of 50. 3548 3549 Collective on MPI_Comm 3550 3551 Input Parameters: 3552 + comm - MPI communicator, set to PETSC_COMM_SELF 3553 . m - number of rows 3554 . n - number of columns 3555 . nz - number of nonzeros per row (same for all rows) 3556 - nnz - array containing the number of nonzeros in the various rows 3557 (possibly different for each row) or NULL 3558 3559 Output Parameter: 3560 . A - the matrix 3561 3562 It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 3563 MatXXXXSetPreallocation() paradgm instead of this routine directly. 3564 [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 3565 3566 Notes: 3567 If nnz is given then nz is ignored 3568 3569 The AIJ format (also called the Yale sparse matrix format or 3570 compressed row storage), is fully compatible with standard Fortran 77 3571 storage. That is, the stored row and column indices can begin at 3572 either one (as in Fortran) or zero. See the users' manual for details. 3573 3574 Specify the preallocated storage with either nz or nnz (not both). 3575 Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 3576 allocation. For large problems you MUST preallocate memory or you 3577 will get TERRIBLE performance, see the users' manual chapter on matrices. 3578 3579 By default, this format uses inodes (identical nodes) when possible, to 3580 improve numerical efficiency of matrix-vector products and solves. We 3581 search for consecutive rows with the same nonzero structure, thereby 3582 reusing matrix information to achieve increased efficiency. 3583 3584 Options Database Keys: 3585 + -mat_no_inode - Do not use inodes 3586 - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3587 3588 Level: intermediate 3589 3590 .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays() 3591 3592 @*/ 3593 PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A) 3594 { 3595 PetscErrorCode ierr; 3596 3597 PetscFunctionBegin; 3598 ierr = MatCreate(comm,A);CHKERRQ(ierr); 3599 ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr); 3600 ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr); 3601 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr); 3602 PetscFunctionReturn(0); 3603 } 3604 3605 #undef __FUNCT__ 3606 #define __FUNCT__ "MatSeqAIJSetPreallocation" 3607 /*@C 3608 MatSeqAIJSetPreallocation - For good matrix assembly performance 3609 the user should preallocate the matrix storage by setting the parameter nz 3610 (or the array nnz). By setting these parameters accurately, performance 3611 during matrix assembly can be increased by more than a factor of 50. 3612 3613 Collective on MPI_Comm 3614 3615 Input Parameters: 3616 + B - The matrix 3617 . nz - number of nonzeros per row (same for all rows) 3618 - nnz - array containing the number of nonzeros in the various rows 3619 (possibly different for each row) or NULL 3620 3621 Notes: 3622 If nnz is given then nz is ignored 3623 3624 The AIJ format (also called the Yale sparse matrix format or 3625 compressed row storage), is fully compatible with standard Fortran 77 3626 storage. That is, the stored row and column indices can begin at 3627 either one (as in Fortran) or zero. See the users' manual for details. 3628 3629 Specify the preallocated storage with either nz or nnz (not both). 3630 Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 3631 allocation. For large problems you MUST preallocate memory or you 3632 will get TERRIBLE performance, see the users' manual chapter on matrices. 3633 3634 You can call MatGetInfo() to get information on how effective the preallocation was; 3635 for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 3636 You can also run with the option -info and look for messages with the string 3637 malloc in them to see if additional memory allocation was needed. 3638 3639 Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix 3640 entries or columns indices 3641 3642 By default, this format uses inodes (identical nodes) when possible, to 3643 improve numerical efficiency of matrix-vector products and solves. We 3644 search for consecutive rows with the same nonzero structure, thereby 3645 reusing matrix information to achieve increased efficiency. 3646 3647 Options Database Keys: 3648 + -mat_no_inode - Do not use inodes 3649 . -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3650 - -mat_aij_oneindex - Internally use indexing starting at 1 3651 rather than 0. Note that when calling MatSetValues(), 3652 the user still MUST index entries starting at 0! 3653 3654 Level: intermediate 3655 3656 .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo() 3657 3658 @*/ 3659 PetscErrorCode MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[]) 3660 { 3661 PetscErrorCode ierr; 3662 3663 PetscFunctionBegin; 3664 PetscValidHeaderSpecific(B,MAT_CLASSID,1); 3665 PetscValidType(B,1); 3666 ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr); 3667 PetscFunctionReturn(0); 3668 } 3669 3670 #undef __FUNCT__ 3671 #define __FUNCT__ "MatSeqAIJSetPreallocation_SeqAIJ" 3672 PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz) 3673 { 3674 Mat_SeqAIJ *b; 3675 PetscBool skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE; 3676 PetscErrorCode ierr; 3677 PetscInt i; 3678 3679 PetscFunctionBegin; 3680 if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 3681 if (nz == MAT_SKIP_ALLOCATION) { 3682 skipallocation = PETSC_TRUE; 3683 nz = 0; 3684 } 3685 3686 ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 3687 ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 3688 3689 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 3690 if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz); 3691 if (nnz) { 3692 for (i=0; i<B->rmap->n; i++) { 3693 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]); 3694 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); 3695 } 3696 } 3697 3698 B->preallocated = PETSC_TRUE; 3699 3700 b = (Mat_SeqAIJ*)B->data; 3701 3702 if (!skipallocation) { 3703 if (!b->imax) { 3704 ierr = PetscMalloc2(B->rmap->n,&b->imax,B->rmap->n,&b->ilen);CHKERRQ(ierr); 3705 ierr = PetscLogObjectMemory((PetscObject)B,2*B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 3706 } 3707 if (!nnz) { 3708 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 3709 else if (nz < 0) nz = 1; 3710 for (i=0; i<B->rmap->n; i++) b->imax[i] = nz; 3711 nz = nz*B->rmap->n; 3712 } else { 3713 nz = 0; 3714 for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz += nnz[i];} 3715 } 3716 /* b->ilen will count nonzeros in each row so far. */ 3717 for (i=0; i<B->rmap->n; i++) b->ilen[i] = 0; 3718 3719 /* allocate the matrix space */ 3720 ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr); 3721 ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr); 3722 ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr); 3723 b->i[0] = 0; 3724 for (i=1; i<B->rmap->n+1; i++) { 3725 b->i[i] = b->i[i-1] + b->imax[i-1]; 3726 } 3727 b->singlemalloc = PETSC_TRUE; 3728 b->free_a = PETSC_TRUE; 3729 b->free_ij = PETSC_TRUE; 3730 #if defined(PETSC_THREADCOMM_ACTIVE) 3731 ierr = MatZeroEntries_SeqAIJ(B);CHKERRQ(ierr); 3732 #endif 3733 } else { 3734 b->free_a = PETSC_FALSE; 3735 b->free_ij = PETSC_FALSE; 3736 } 3737 3738 b->nz = 0; 3739 b->maxnz = nz; 3740 B->info.nz_unneeded = (double)b->maxnz; 3741 if (realalloc) { 3742 ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 3743 } 3744 PetscFunctionReturn(0); 3745 } 3746 3747 #undef __FUNCT__ 3748 #define __FUNCT__ "MatSeqAIJSetPreallocationCSR" 3749 /*@ 3750 MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format. 3751 3752 Input Parameters: 3753 + B - the matrix 3754 . i - the indices into j for the start of each row (starts with zero) 3755 . j - the column indices for each row (starts with zero) these must be sorted for each row 3756 - v - optional values in the matrix 3757 3758 Level: developer 3759 3760 The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays() 3761 3762 .keywords: matrix, aij, compressed row, sparse, sequential 3763 3764 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), SeqAIJ 3765 @*/ 3766 PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[]) 3767 { 3768 PetscErrorCode ierr; 3769 3770 PetscFunctionBegin; 3771 PetscValidHeaderSpecific(B,MAT_CLASSID,1); 3772 PetscValidType(B,1); 3773 ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr); 3774 PetscFunctionReturn(0); 3775 } 3776 3777 #undef __FUNCT__ 3778 #define __FUNCT__ "MatSeqAIJSetPreallocationCSR_SeqAIJ" 3779 PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[]) 3780 { 3781 PetscInt i; 3782 PetscInt m,n; 3783 PetscInt nz; 3784 PetscInt *nnz, nz_max = 0; 3785 PetscScalar *values; 3786 PetscErrorCode ierr; 3787 3788 PetscFunctionBegin; 3789 if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]); 3790 3791 ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 3792 ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 3793 3794 ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr); 3795 ierr = PetscMalloc1((m+1), &nnz);CHKERRQ(ierr); 3796 for (i = 0; i < m; i++) { 3797 nz = Ii[i+1]- Ii[i]; 3798 nz_max = PetscMax(nz_max, nz); 3799 if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz); 3800 nnz[i] = nz; 3801 } 3802 ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr); 3803 ierr = PetscFree(nnz);CHKERRQ(ierr); 3804 3805 if (v) { 3806 values = (PetscScalar*) v; 3807 } else { 3808 ierr = PetscCalloc1(nz_max, &values);CHKERRQ(ierr); 3809 } 3810 3811 for (i = 0; i < m; i++) { 3812 nz = Ii[i+1] - Ii[i]; 3813 ierr = MatSetValues_SeqAIJ(B, 1, &i, nz, J+Ii[i], values + (v ? Ii[i] : 0), INSERT_VALUES);CHKERRQ(ierr); 3814 } 3815 3816 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3817 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3818 3819 if (!v) { 3820 ierr = PetscFree(values);CHKERRQ(ierr); 3821 } 3822 ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 3823 PetscFunctionReturn(0); 3824 } 3825 3826 #include <../src/mat/impls/dense/seq/dense.h> 3827 #include <petsc-private/kernels/petscaxpy.h> 3828 3829 #undef __FUNCT__ 3830 #define __FUNCT__ "MatMatMultNumeric_SeqDense_SeqAIJ" 3831 /* 3832 Computes (B'*A')' since computing B*A directly is untenable 3833 3834 n p p 3835 ( ) ( ) ( ) 3836 m ( A ) * n ( B ) = m ( C ) 3837 ( ) ( ) ( ) 3838 3839 */ 3840 PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C) 3841 { 3842 PetscErrorCode ierr; 3843 Mat_SeqDense *sub_a = (Mat_SeqDense*)A->data; 3844 Mat_SeqAIJ *sub_b = (Mat_SeqAIJ*)B->data; 3845 Mat_SeqDense *sub_c = (Mat_SeqDense*)C->data; 3846 PetscInt i,n,m,q,p; 3847 const PetscInt *ii,*idx; 3848 const PetscScalar *b,*a,*a_q; 3849 PetscScalar *c,*c_q; 3850 3851 PetscFunctionBegin; 3852 m = A->rmap->n; 3853 n = A->cmap->n; 3854 p = B->cmap->n; 3855 a = sub_a->v; 3856 b = sub_b->a; 3857 c = sub_c->v; 3858 ierr = PetscMemzero(c,m*p*sizeof(PetscScalar));CHKERRQ(ierr); 3859 3860 ii = sub_b->i; 3861 idx = sub_b->j; 3862 for (i=0; i<n; i++) { 3863 q = ii[i+1] - ii[i]; 3864 while (q-->0) { 3865 c_q = c + m*(*idx); 3866 a_q = a + m*i; 3867 PetscKernelAXPY(c_q,*b,a_q,m); 3868 idx++; 3869 b++; 3870 } 3871 } 3872 PetscFunctionReturn(0); 3873 } 3874 3875 #undef __FUNCT__ 3876 #define __FUNCT__ "MatMatMultSymbolic_SeqDense_SeqAIJ" 3877 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat *C) 3878 { 3879 PetscErrorCode ierr; 3880 PetscInt m=A->rmap->n,n=B->cmap->n; 3881 Mat Cmat; 3882 3883 PetscFunctionBegin; 3884 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); 3885 ierr = MatCreate(PetscObjectComm((PetscObject)A),&Cmat);CHKERRQ(ierr); 3886 ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr); 3887 ierr = MatSetBlockSizesFromMats(Cmat,A,B);CHKERRQ(ierr); 3888 ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr); 3889 ierr = MatSeqDenseSetPreallocation(Cmat,NULL);CHKERRQ(ierr); 3890 3891 Cmat->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ; 3892 3893 *C = Cmat; 3894 PetscFunctionReturn(0); 3895 } 3896 3897 /* ----------------------------------------------------------------*/ 3898 #undef __FUNCT__ 3899 #define __FUNCT__ "MatMatMult_SeqDense_SeqAIJ" 3900 PetscErrorCode MatMatMult_SeqDense_SeqAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 3901 { 3902 PetscErrorCode ierr; 3903 3904 PetscFunctionBegin; 3905 if (scall == MAT_INITIAL_MATRIX) { 3906 ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 3907 ierr = MatMatMultSymbolic_SeqDense_SeqAIJ(A,B,fill,C);CHKERRQ(ierr); 3908 ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 3909 } 3910 ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 3911 ierr = MatMatMultNumeric_SeqDense_SeqAIJ(A,B,*C);CHKERRQ(ierr); 3912 ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 3913 PetscFunctionReturn(0); 3914 } 3915 3916 3917 /*MC 3918 MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 3919 based on compressed sparse row format. 3920 3921 Options Database Keys: 3922 . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 3923 3924 Level: beginner 3925 3926 .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType 3927 M*/ 3928 3929 /*MC 3930 MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 3931 3932 This matrix type is identical to MATSEQAIJ when constructed with a single process communicator, 3933 and MATMPIAIJ otherwise. As a result, for single process communicators, 3934 MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation is supported 3935 for communicators controlling multiple processes. It is recommended that you call both of 3936 the above preallocation routines for simplicity. 3937 3938 Options Database Keys: 3939 . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions() 3940 3941 Developer Notes: Subclasses include MATAIJCUSP, MATAIJPERM, MATAIJCRL, and also automatically switches over to use inodes when 3942 enough exist. 3943 3944 Level: beginner 3945 3946 .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ 3947 M*/ 3948 3949 /*MC 3950 MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 3951 3952 This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator, 3953 and MATMPIAIJCRL otherwise. As a result, for single process communicators, 3954 MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 3955 for communicators controlling multiple processes. It is recommended that you call both of 3956 the above preallocation routines for simplicity. 3957 3958 Options Database Keys: 3959 . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions() 3960 3961 Level: beginner 3962 3963 .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL 3964 M*/ 3965 3966 #if defined(PETSC_HAVE_PASTIX) 3967 PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_pastix(Mat,MatFactorType,Mat*); 3968 #endif 3969 #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) 3970 PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_essl(Mat,MatFactorType,Mat*); 3971 #endif 3972 PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*); 3973 #if defined(PETSC_HAVE_ELEMENTAL) 3974 PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*); 3975 #endif 3976 PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_petsc(Mat,MatFactorType,Mat*); 3977 PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_bas(Mat,MatFactorType,Mat*); 3978 extern PetscErrorCode MatGetFactorAvailable_seqaij_petsc(Mat,MatFactorType,PetscBool*); 3979 #if defined(PETSC_HAVE_MUMPS) 3980 PETSC_EXTERN PetscErrorCode MatGetFactor_aij_mumps(Mat,MatFactorType,Mat*); 3981 #endif 3982 #if defined(PETSC_HAVE_SUPERLU) 3983 PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_superlu(Mat,MatFactorType,Mat*); 3984 #endif 3985 #if defined(PETSC_HAVE_MKL_PARDISO) 3986 PETSC_EXTERN PetscErrorCode MatGetFactor_aij_mkl_pardiso(Mat,MatFactorType,Mat*); 3987 #endif 3988 #if defined(PETSC_HAVE_SUPERLU_DIST) 3989 PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_superlu_dist(Mat,MatFactorType,Mat*); 3990 #endif 3991 #if defined(PETSC_HAVE_SUITESPARSE) 3992 PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_umfpack(Mat,MatFactorType,Mat*); 3993 #endif 3994 #if defined(PETSC_HAVE_SUITESPARSE) 3995 PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_cholmod(Mat,MatFactorType,Mat*); 3996 #endif 3997 #if defined(PETSC_HAVE_SUITESPARSE) 3998 PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_klu(Mat,MatFactorType,Mat*); 3999 #endif 4000 #if defined(PETSC_HAVE_LUSOL) 4001 PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_lusol(Mat,MatFactorType,Mat*); 4002 #endif 4003 #if defined(PETSC_HAVE_MATLAB_ENGINE) 4004 PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_matlab(Mat,MatFactorType,Mat*); 4005 extern PetscErrorCode MatlabEnginePut_SeqAIJ(PetscObject,void*); 4006 extern PetscErrorCode MatlabEngineGet_SeqAIJ(PetscObject,void*); 4007 #endif 4008 #if defined(PETSC_HAVE_CLIQUE) 4009 PETSC_EXTERN PetscErrorCode MatGetFactor_aij_clique(Mat,MatFactorType,Mat*); 4010 #endif 4011 4012 4013 #undef __FUNCT__ 4014 #define __FUNCT__ "MatSeqAIJGetArray" 4015 /*@C 4016 MatSeqAIJGetArray - gives access to the array where the data for a SeqSeqAIJ matrix is stored 4017 4018 Not Collective 4019 4020 Input Parameter: 4021 . mat - a MATSEQAIJ matrix 4022 4023 Output Parameter: 4024 . array - pointer to the data 4025 4026 Level: intermediate 4027 4028 .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90() 4029 @*/ 4030 PetscErrorCode MatSeqAIJGetArray(Mat A,PetscScalar **array) 4031 { 4032 PetscErrorCode ierr; 4033 4034 PetscFunctionBegin; 4035 ierr = PetscUseMethod(A,"MatSeqAIJGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr); 4036 PetscFunctionReturn(0); 4037 } 4038 4039 #undef __FUNCT__ 4040 #define __FUNCT__ "MatSeqAIJGetMaxRowNonzeros" 4041 /*@C 4042 MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row 4043 4044 Not Collective 4045 4046 Input Parameter: 4047 . mat - a MATSEQAIJ matrix 4048 4049 Output Parameter: 4050 . nz - the maximum number of nonzeros in any row 4051 4052 Level: intermediate 4053 4054 .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90() 4055 @*/ 4056 PetscErrorCode MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz) 4057 { 4058 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4059 4060 PetscFunctionBegin; 4061 *nz = aij->rmax; 4062 PetscFunctionReturn(0); 4063 } 4064 4065 #undef __FUNCT__ 4066 #define __FUNCT__ "MatSeqAIJRestoreArray" 4067 /*@C 4068 MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray() 4069 4070 Not Collective 4071 4072 Input Parameters: 4073 . mat - a MATSEQAIJ matrix 4074 . array - pointer to the data 4075 4076 Level: intermediate 4077 4078 .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90() 4079 @*/ 4080 PetscErrorCode MatSeqAIJRestoreArray(Mat A,PetscScalar **array) 4081 { 4082 PetscErrorCode ierr; 4083 4084 PetscFunctionBegin; 4085 ierr = PetscUseMethod(A,"MatSeqAIJRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr); 4086 PetscFunctionReturn(0); 4087 } 4088 4089 #undef __FUNCT__ 4090 #define __FUNCT__ "MatCreate_SeqAIJ" 4091 PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B) 4092 { 4093 Mat_SeqAIJ *b; 4094 PetscErrorCode ierr; 4095 PetscMPIInt size; 4096 4097 PetscFunctionBegin; 4098 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr); 4099 if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1"); 4100 4101 ierr = PetscNewLog(B,&b);CHKERRQ(ierr); 4102 4103 B->data = (void*)b; 4104 4105 ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 4106 4107 b->row = 0; 4108 b->col = 0; 4109 b->icol = 0; 4110 b->reallocs = 0; 4111 b->ignorezeroentries = PETSC_FALSE; 4112 b->roworiented = PETSC_TRUE; 4113 b->nonew = 0; 4114 b->diag = 0; 4115 b->solve_work = 0; 4116 B->spptr = 0; 4117 b->saved_values = 0; 4118 b->idiag = 0; 4119 b->mdiag = 0; 4120 b->ssor_work = 0; 4121 b->omega = 1.0; 4122 b->fshift = 0.0; 4123 b->idiagvalid = PETSC_FALSE; 4124 b->ibdiagvalid = PETSC_FALSE; 4125 b->keepnonzeropattern = PETSC_FALSE; 4126 b->xtoy = 0; 4127 b->XtoY = 0; 4128 4129 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 4130 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJGetArray_C",MatSeqAIJGetArray_SeqAIJ);CHKERRQ(ierr); 4131 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJRestoreArray_C",MatSeqAIJRestoreArray_SeqAIJ);CHKERRQ(ierr); 4132 4133 #if defined(PETSC_HAVE_MATLAB_ENGINE) 4134 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactor_matlab_C",MatGetFactor_seqaij_matlab);CHKERRQ(ierr); 4135 ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr); 4136 ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr); 4137 #endif 4138 #if defined(PETSC_HAVE_PASTIX) 4139 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactor_pastix_C",MatGetFactor_seqaij_pastix);CHKERRQ(ierr); 4140 #endif 4141 #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) 4142 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactor_essl_C",MatGetFactor_seqaij_essl);CHKERRQ(ierr); 4143 #endif 4144 #if defined(PETSC_HAVE_SUPERLU) 4145 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactor_superlu_C",MatGetFactor_seqaij_superlu);CHKERRQ(ierr); 4146 #endif 4147 #if defined(PETSC_HAVE_MKL_PARDISO) 4148 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactor_mkl_pardiso_C",MatGetFactor_aij_mkl_pardiso);CHKERRQ(ierr); 4149 #endif 4150 #if defined(PETSC_HAVE_SUPERLU_DIST) 4151 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactor_superlu_dist_C",MatGetFactor_seqaij_superlu_dist);CHKERRQ(ierr); 4152 #endif 4153 #if defined(PETSC_HAVE_MUMPS) 4154 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactor_mumps_C",MatGetFactor_aij_mumps);CHKERRQ(ierr); 4155 #endif 4156 #if defined(PETSC_HAVE_SUITESPARSE) 4157 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactor_umfpack_C",MatGetFactor_seqaij_umfpack);CHKERRQ(ierr); 4158 #endif 4159 #if defined(PETSC_HAVE_SUITESPARSE) 4160 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactor_cholmod_C",MatGetFactor_seqaij_cholmod);CHKERRQ(ierr); 4161 #endif 4162 #if defined(PETSC_HAVE_SUITESPARSE) 4163 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactor_klu_C",MatGetFactor_seqaij_klu);CHKERRQ(ierr); 4164 #endif 4165 #if defined(PETSC_HAVE_LUSOL) 4166 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactor_lusol_C",MatGetFactor_seqaij_lusol);CHKERRQ(ierr); 4167 #endif 4168 #if defined(PETSC_HAVE_CLIQUE) 4169 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactor_clique_C",MatGetFactor_aij_clique);CHKERRQ(ierr); 4170 #endif 4171 4172 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactor_petsc_C",MatGetFactor_seqaij_petsc);CHKERRQ(ierr); 4173 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactorAvailable_petsc_C",MatGetFactorAvailable_seqaij_petsc);CHKERRQ(ierr); 4174 ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetFactor_bas_C",MatGetFactor_seqaij_bas);CHKERRQ(ierr); 4175 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr); 4176 ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr); 4177 ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr); 4178 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr); 4179 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr); 4180 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr); 4181 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr); 4182 #if defined(PETSC_HAVE_ELEMENTAL) 4183 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr); 4184 #endif 4185 ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr); 4186 ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr); 4187 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr); 4188 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr); 4189 ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr); 4190 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqdense_seqaij_C",MatMatMult_SeqDense_SeqAIJ);CHKERRQ(ierr); 4191 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaij_C",MatMatMultSymbolic_SeqDense_SeqAIJ);CHKERRQ(ierr); 4192 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqdense_seqaij_C",MatMatMultNumeric_SeqDense_SeqAIJ);CHKERRQ(ierr); 4193 ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr); 4194 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 4195 PetscFunctionReturn(0); 4196 } 4197 4198 #undef __FUNCT__ 4199 #define __FUNCT__ "MatDuplicateNoCreate_SeqAIJ" 4200 /* 4201 Given a matrix generated with MatGetFactor() duplicates all the information in A into B 4202 */ 4203 PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace) 4204 { 4205 Mat_SeqAIJ *c,*a = (Mat_SeqAIJ*)A->data; 4206 PetscErrorCode ierr; 4207 PetscInt i,m = A->rmap->n; 4208 4209 PetscFunctionBegin; 4210 c = (Mat_SeqAIJ*)C->data; 4211 4212 C->factortype = A->factortype; 4213 c->row = 0; 4214 c->col = 0; 4215 c->icol = 0; 4216 c->reallocs = 0; 4217 4218 C->assembled = PETSC_TRUE; 4219 4220 ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr); 4221 ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr); 4222 4223 ierr = PetscMalloc2(m,&c->imax,m,&c->ilen);CHKERRQ(ierr); 4224 ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr); 4225 for (i=0; i<m; i++) { 4226 c->imax[i] = a->imax[i]; 4227 c->ilen[i] = a->ilen[i]; 4228 } 4229 4230 /* allocate the matrix space */ 4231 if (mallocmatspace) { 4232 ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr); 4233 ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 4234 4235 c->singlemalloc = PETSC_TRUE; 4236 4237 ierr = PetscMemcpy(c->i,a->i,(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 4238 if (m > 0) { 4239 ierr = PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(PetscInt));CHKERRQ(ierr); 4240 if (cpvalues == MAT_COPY_VALUES) { 4241 ierr = PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr); 4242 } else { 4243 ierr = PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr); 4244 } 4245 } 4246 } 4247 4248 c->ignorezeroentries = a->ignorezeroentries; 4249 c->roworiented = a->roworiented; 4250 c->nonew = a->nonew; 4251 if (a->diag) { 4252 ierr = PetscMalloc1((m+1),&c->diag);CHKERRQ(ierr); 4253 ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 4254 for (i=0; i<m; i++) { 4255 c->diag[i] = a->diag[i]; 4256 } 4257 } else c->diag = 0; 4258 4259 c->solve_work = 0; 4260 c->saved_values = 0; 4261 c->idiag = 0; 4262 c->ssor_work = 0; 4263 c->keepnonzeropattern = a->keepnonzeropattern; 4264 c->free_a = PETSC_TRUE; 4265 c->free_ij = PETSC_TRUE; 4266 c->xtoy = 0; 4267 c->XtoY = 0; 4268 4269 c->rmax = a->rmax; 4270 c->nz = a->nz; 4271 c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 4272 C->preallocated = PETSC_TRUE; 4273 4274 c->compressedrow.use = a->compressedrow.use; 4275 c->compressedrow.nrows = a->compressedrow.nrows; 4276 if (a->compressedrow.use) { 4277 i = a->compressedrow.nrows; 4278 ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr); 4279 ierr = PetscMemcpy(c->compressedrow.i,a->compressedrow.i,(i+1)*sizeof(PetscInt));CHKERRQ(ierr); 4280 ierr = PetscMemcpy(c->compressedrow.rindex,a->compressedrow.rindex,i*sizeof(PetscInt));CHKERRQ(ierr); 4281 } else { 4282 c->compressedrow.use = PETSC_FALSE; 4283 c->compressedrow.i = NULL; 4284 c->compressedrow.rindex = NULL; 4285 } 4286 C->nonzerostate = A->nonzerostate; 4287 4288 ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr); 4289 ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr); 4290 PetscFunctionReturn(0); 4291 } 4292 4293 #undef __FUNCT__ 4294 #define __FUNCT__ "MatDuplicate_SeqAIJ" 4295 PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B) 4296 { 4297 PetscErrorCode ierr; 4298 4299 PetscFunctionBegin; 4300 ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr); 4301 ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr); 4302 if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) { 4303 ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr); 4304 } 4305 ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr); 4306 ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr); 4307 PetscFunctionReturn(0); 4308 } 4309 4310 #undef __FUNCT__ 4311 #define __FUNCT__ "MatLoad_SeqAIJ" 4312 PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer) 4313 { 4314 Mat_SeqAIJ *a; 4315 PetscErrorCode ierr; 4316 PetscInt i,sum,nz,header[4],*rowlengths = 0,M,N,rows,cols; 4317 int fd; 4318 PetscMPIInt size; 4319 MPI_Comm comm; 4320 PetscInt bs = 1; 4321 4322 PetscFunctionBegin; 4323 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 4324 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 4325 if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"view must have one processor"); 4326 4327 ierr = PetscOptionsBegin(comm,NULL,"Options for loading SEQAIJ matrix","Mat");CHKERRQ(ierr); 4328 ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,NULL);CHKERRQ(ierr); 4329 ierr = PetscOptionsEnd();CHKERRQ(ierr); 4330 if (bs > 1) {ierr = MatSetBlockSize(newMat,bs);CHKERRQ(ierr);} 4331 4332 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 4333 ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr); 4334 if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file"); 4335 M = header[1]; N = header[2]; nz = header[3]; 4336 4337 if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ"); 4338 4339 /* read in row lengths */ 4340 ierr = PetscMalloc1(M,&rowlengths);CHKERRQ(ierr); 4341 ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr); 4342 4343 /* check if sum of rowlengths is same as nz */ 4344 for (i=0,sum=0; i< M; i++) sum +=rowlengths[i]; 4345 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); 4346 4347 /* set global size if not set already*/ 4348 if (newMat->rmap->n < 0 && newMat->rmap->N < 0 && newMat->cmap->n < 0 && newMat->cmap->N < 0) { 4349 ierr = MatSetSizes(newMat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 4350 } else { 4351 /* if sizes and type are already set, check if the vector global sizes are correct */ 4352 ierr = MatGetSize(newMat,&rows,&cols);CHKERRQ(ierr); 4353 if (rows < 0 && cols < 0) { /* user might provide local size instead of global size */ 4354 ierr = MatGetLocalSize(newMat,&rows,&cols);CHKERRQ(ierr); 4355 } 4356 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); 4357 } 4358 ierr = MatSeqAIJSetPreallocation_SeqAIJ(newMat,0,rowlengths);CHKERRQ(ierr); 4359 a = (Mat_SeqAIJ*)newMat->data; 4360 4361 ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT);CHKERRQ(ierr); 4362 4363 /* read in nonzero values */ 4364 ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);CHKERRQ(ierr); 4365 4366 /* set matrix "i" values */ 4367 a->i[0] = 0; 4368 for (i=1; i<= M; i++) { 4369 a->i[i] = a->i[i-1] + rowlengths[i-1]; 4370 a->ilen[i-1] = rowlengths[i-1]; 4371 } 4372 ierr = PetscFree(rowlengths);CHKERRQ(ierr); 4373 4374 ierr = MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4375 ierr = MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4376 PetscFunctionReturn(0); 4377 } 4378 4379 #undef __FUNCT__ 4380 #define __FUNCT__ "MatEqual_SeqAIJ" 4381 PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg) 4382 { 4383 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data; 4384 PetscErrorCode ierr; 4385 #if defined(PETSC_USE_COMPLEX) 4386 PetscInt k; 4387 #endif 4388 4389 PetscFunctionBegin; 4390 /* If the matrix dimensions are not equal,or no of nonzeros */ 4391 if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) { 4392 *flg = PETSC_FALSE; 4393 PetscFunctionReturn(0); 4394 } 4395 4396 /* if the a->i are the same */ 4397 ierr = PetscMemcmp(a->i,b->i,(A->rmap->n+1)*sizeof(PetscInt),flg);CHKERRQ(ierr); 4398 if (!*flg) PetscFunctionReturn(0); 4399 4400 /* if a->j are the same */ 4401 ierr = PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),flg);CHKERRQ(ierr); 4402 if (!*flg) PetscFunctionReturn(0); 4403 4404 /* if a->a are the same */ 4405 #if defined(PETSC_USE_COMPLEX) 4406 for (k=0; k<a->nz; k++) { 4407 if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])) { 4408 *flg = PETSC_FALSE; 4409 PetscFunctionReturn(0); 4410 } 4411 } 4412 #else 4413 ierr = PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);CHKERRQ(ierr); 4414 #endif 4415 PetscFunctionReturn(0); 4416 } 4417 4418 #undef __FUNCT__ 4419 #define __FUNCT__ "MatCreateSeqAIJWithArrays" 4420 /*@ 4421 MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format) 4422 provided by the user. 4423 4424 Collective on MPI_Comm 4425 4426 Input Parameters: 4427 + comm - must be an MPI communicator of size 1 4428 . m - number of rows 4429 . n - number of columns 4430 . i - row indices 4431 . j - column indices 4432 - a - matrix values 4433 4434 Output Parameter: 4435 . mat - the matrix 4436 4437 Level: intermediate 4438 4439 Notes: 4440 The i, j, and a arrays are not copied by this routine, the user must free these arrays 4441 once the matrix is destroyed and not before 4442 4443 You cannot set new nonzero locations into this matrix, that will generate an error. 4444 4445 The i and j indices are 0 based 4446 4447 The format which is used for the sparse matrix input, is equivalent to a 4448 row-major ordering.. i.e for the following matrix, the input data expected is 4449 as shown: 4450 4451 1 0 0 4452 2 0 3 4453 4 5 6 4454 4455 i = {0,1,3,6} [size = nrow+1 = 3+1] 4456 j = {0,0,2,0,1,2} [size = nz = 6]; values must be sorted for each row 4457 v = {1,2,3,4,5,6} [size = nz = 6] 4458 4459 4460 .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR() 4461 4462 @*/ 4463 PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt *i,PetscInt *j,PetscScalar *a,Mat *mat) 4464 { 4465 PetscErrorCode ierr; 4466 PetscInt ii; 4467 Mat_SeqAIJ *aij; 4468 #if defined(PETSC_USE_DEBUG) 4469 PetscInt jj; 4470 #endif 4471 4472 PetscFunctionBegin; 4473 if (i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 4474 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 4475 ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr); 4476 /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */ 4477 ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr); 4478 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr); 4479 aij = (Mat_SeqAIJ*)(*mat)->data; 4480 ierr = PetscMalloc2(m,&aij->imax,m,&aij->ilen);CHKERRQ(ierr); 4481 4482 aij->i = i; 4483 aij->j = j; 4484 aij->a = a; 4485 aij->singlemalloc = PETSC_FALSE; 4486 aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 4487 aij->free_a = PETSC_FALSE; 4488 aij->free_ij = PETSC_FALSE; 4489 4490 for (ii=0; ii<m; ii++) { 4491 aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii]; 4492 #if defined(PETSC_USE_DEBUG) 4493 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]); 4494 for (jj=i[ii]+1; jj<i[ii+1]; jj++) { 4495 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); 4496 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); 4497 } 4498 #endif 4499 } 4500 #if defined(PETSC_USE_DEBUG) 4501 for (ii=0; ii<aij->i[m]; ii++) { 4502 if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]); 4503 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]); 4504 } 4505 #endif 4506 4507 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4508 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4509 PetscFunctionReturn(0); 4510 } 4511 #undef __FUNCT__ 4512 #define __FUNCT__ "MatCreateSeqAIJFromTriple" 4513 /*@C 4514 MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format) 4515 provided by the user. 4516 4517 Collective on MPI_Comm 4518 4519 Input Parameters: 4520 + comm - must be an MPI communicator of size 1 4521 . m - number of rows 4522 . n - number of columns 4523 . i - row indices 4524 . j - column indices 4525 . a - matrix values 4526 . nz - number of nonzeros 4527 - idx - 0 or 1 based 4528 4529 Output Parameter: 4530 . mat - the matrix 4531 4532 Level: intermediate 4533 4534 Notes: 4535 The i and j indices are 0 based 4536 4537 The format which is used for the sparse matrix input, is equivalent to a 4538 row-major ordering.. i.e for the following matrix, the input data expected is 4539 as shown: 4540 4541 1 0 0 4542 2 0 3 4543 4 5 6 4544 4545 i = {0,1,1,2,2,2} 4546 j = {0,0,2,0,1,2} 4547 v = {1,2,3,4,5,6} 4548 4549 4550 .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR() 4551 4552 @*/ 4553 PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt *i,PetscInt *j,PetscScalar *a,Mat *mat,PetscInt nz,PetscBool idx) 4554 { 4555 PetscErrorCode ierr; 4556 PetscInt ii, *nnz, one = 1,row,col; 4557 4558 4559 PetscFunctionBegin; 4560 ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr); 4561 for (ii = 0; ii < nz; ii++) { 4562 nnz[i[ii] - !!idx] += 1; 4563 } 4564 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 4565 ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr); 4566 ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr); 4567 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr); 4568 for (ii = 0; ii < nz; ii++) { 4569 if (idx) { 4570 row = i[ii] - 1; 4571 col = j[ii] - 1; 4572 } else { 4573 row = i[ii]; 4574 col = j[ii]; 4575 } 4576 ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr); 4577 } 4578 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4579 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4580 ierr = PetscFree(nnz);CHKERRQ(ierr); 4581 PetscFunctionReturn(0); 4582 } 4583 4584 #undef __FUNCT__ 4585 #define __FUNCT__ "MatSetColoring_SeqAIJ" 4586 PetscErrorCode MatSetColoring_SeqAIJ(Mat A,ISColoring coloring) 4587 { 4588 PetscErrorCode ierr; 4589 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 4590 4591 PetscFunctionBegin; 4592 if (coloring->ctype == IS_COLORING_GLOBAL) { 4593 ierr = ISColoringReference(coloring);CHKERRQ(ierr); 4594 a->coloring = coloring; 4595 } else if (coloring->ctype == IS_COLORING_GHOSTED) { 4596 PetscInt i,*larray; 4597 ISColoring ocoloring; 4598 ISColoringValue *colors; 4599 4600 /* set coloring for diagonal portion */ 4601 ierr = PetscMalloc1(A->cmap->n,&larray);CHKERRQ(ierr); 4602 for (i=0; i<A->cmap->n; i++) larray[i] = i; 4603 ierr = ISGlobalToLocalMappingApply(A->cmap->mapping,IS_GTOLM_MASK,A->cmap->n,larray,NULL,larray);CHKERRQ(ierr); 4604 ierr = PetscMalloc1(A->cmap->n,&colors);CHKERRQ(ierr); 4605 for (i=0; i<A->cmap->n; i++) colors[i] = coloring->colors[larray[i]]; 4606 ierr = PetscFree(larray);CHKERRQ(ierr); 4607 ierr = ISColoringCreate(PETSC_COMM_SELF,coloring->n,A->cmap->n,colors,&ocoloring);CHKERRQ(ierr); 4608 a->coloring = ocoloring; 4609 } 4610 PetscFunctionReturn(0); 4611 } 4612 4613 #undef __FUNCT__ 4614 #define __FUNCT__ "MatSetValuesAdifor_SeqAIJ" 4615 PetscErrorCode MatSetValuesAdifor_SeqAIJ(Mat A,PetscInt nl,void *advalues) 4616 { 4617 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 4618 PetscInt m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j; 4619 MatScalar *v = a->a; 4620 PetscScalar *values = (PetscScalar*)advalues; 4621 ISColoringValue *color; 4622 4623 PetscFunctionBegin; 4624 if (!a->coloring) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix"); 4625 color = a->coloring->colors; 4626 /* loop over rows */ 4627 for (i=0; i<m; i++) { 4628 nz = ii[i+1] - ii[i]; 4629 /* loop over columns putting computed value into matrix */ 4630 for (j=0; j<nz; j++) *v++ = values[color[*jj++]]; 4631 values += nl; /* jump to next row of derivatives */ 4632 } 4633 PetscFunctionReturn(0); 4634 } 4635 4636 #undef __FUNCT__ 4637 #define __FUNCT__ "MatSeqAIJInvalidateDiagonal" 4638 PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A) 4639 { 4640 Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data; 4641 PetscErrorCode ierr; 4642 4643 PetscFunctionBegin; 4644 a->idiagvalid = PETSC_FALSE; 4645 a->ibdiagvalid = PETSC_FALSE; 4646 4647 ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr); 4648 PetscFunctionReturn(0); 4649 } 4650 4651 #undef __FUNCT__ 4652 #define __FUNCT__ "MatCreateMPIMatConcatenateSeqMat_SeqAIJ" 4653 PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat) 4654 { 4655 PetscErrorCode ierr; 4656 4657 PetscFunctionBegin; 4658 ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr); 4659 PetscFunctionReturn(0); 4660 } 4661 4662 /* 4663 Special version for direct calls from Fortran 4664 */ 4665 #include <petsc-private/fortranimpl.h> 4666 #if defined(PETSC_HAVE_FORTRAN_CAPS) 4667 #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ 4668 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 4669 #define matsetvaluesseqaij_ matsetvaluesseqaij 4670 #endif 4671 4672 /* Change these macros so can be used in void function */ 4673 #undef CHKERRQ 4674 #define CHKERRQ(ierr) CHKERRABORT(PetscObjectComm((PetscObject)A),ierr) 4675 #undef SETERRQ2 4676 #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr) 4677 #undef SETERRQ3 4678 #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr) 4679 4680 #undef __FUNCT__ 4681 #define __FUNCT__ "matsetvaluesseqaij_" 4682 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) 4683 { 4684 Mat A = *AA; 4685 PetscInt m = *mm, n = *nn; 4686 InsertMode is = *isis; 4687 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 4688 PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N; 4689 PetscInt *imax,*ai,*ailen; 4690 PetscErrorCode ierr; 4691 PetscInt *aj,nonew = a->nonew,lastcol = -1; 4692 MatScalar *ap,value,*aa; 4693 PetscBool ignorezeroentries = a->ignorezeroentries; 4694 PetscBool roworiented = a->roworiented; 4695 4696 PetscFunctionBegin; 4697 MatCheckPreallocated(A,1); 4698 imax = a->imax; 4699 ai = a->i; 4700 ailen = a->ilen; 4701 aj = a->j; 4702 aa = a->a; 4703 4704 for (k=0; k<m; k++) { /* loop over added rows */ 4705 row = im[k]; 4706 if (row < 0) continue; 4707 #if defined(PETSC_USE_DEBUG) 4708 if (row >= A->rmap->n) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large"); 4709 #endif 4710 rp = aj + ai[row]; ap = aa + ai[row]; 4711 rmax = imax[row]; nrow = ailen[row]; 4712 low = 0; 4713 high = nrow; 4714 for (l=0; l<n; l++) { /* loop over added columns */ 4715 if (in[l] < 0) continue; 4716 #if defined(PETSC_USE_DEBUG) 4717 if (in[l] >= A->cmap->n) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large"); 4718 #endif 4719 col = in[l]; 4720 if (roworiented) value = v[l + k*n]; 4721 else value = v[k + l*m]; 4722 4723 if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 4724 4725 if (col <= lastcol) low = 0; 4726 else high = nrow; 4727 lastcol = col; 4728 while (high-low > 5) { 4729 t = (low+high)/2; 4730 if (rp[t] > col) high = t; 4731 else low = t; 4732 } 4733 for (i=low; i<high; i++) { 4734 if (rp[i] > col) break; 4735 if (rp[i] == col) { 4736 if (is == ADD_VALUES) ap[i] += value; 4737 else ap[i] = value; 4738 goto noinsert; 4739 } 4740 } 4741 if (value == 0.0 && ignorezeroentries) goto noinsert; 4742 if (nonew == 1) goto noinsert; 4743 if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix"); 4744 MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar); 4745 N = nrow++ - 1; a->nz++; high++; 4746 /* shift up all the later entries in this row */ 4747 for (ii=N; ii>=i; ii--) { 4748 rp[ii+1] = rp[ii]; 4749 ap[ii+1] = ap[ii]; 4750 } 4751 rp[i] = col; 4752 ap[i] = value; 4753 A->nonzerostate++; 4754 noinsert:; 4755 low = i + 1; 4756 } 4757 ailen[row] = nrow; 4758 } 4759 PetscFunctionReturnVoid(); 4760 } 4761 4762