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,"%%%%MatrixMarket matrix coordinate complex general\n");CHKERRQ(ierr); 757 #else 758 ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate 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 = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr); 1129 ierr = PetscFree(a->matmult_abdense);CHKERRQ(ierr); 1130 1131 ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr); 1132 ierr = PetscFree(A->data);CHKERRQ(ierr); 1133 1134 ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 1135 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr); 1136 ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr); 1137 ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr); 1138 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr); 1139 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr); 1140 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr); 1141 #if defined(PETSC_HAVE_ELEMENTAL) 1142 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr); 1143 #endif 1144 ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr); 1145 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr); 1146 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr); 1147 ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr); 1148 PetscFunctionReturn(0); 1149 } 1150 1151 #undef __FUNCT__ 1152 #define __FUNCT__ "MatSetOption_SeqAIJ" 1153 PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg) 1154 { 1155 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1156 PetscErrorCode ierr; 1157 1158 PetscFunctionBegin; 1159 switch (op) { 1160 case MAT_ROW_ORIENTED: 1161 a->roworiented = flg; 1162 break; 1163 case MAT_KEEP_NONZERO_PATTERN: 1164 a->keepnonzeropattern = flg; 1165 break; 1166 case MAT_NEW_NONZERO_LOCATIONS: 1167 a->nonew = (flg ? 0 : 1); 1168 break; 1169 case MAT_NEW_NONZERO_LOCATION_ERR: 1170 a->nonew = (flg ? -1 : 0); 1171 break; 1172 case MAT_NEW_NONZERO_ALLOCATION_ERR: 1173 a->nonew = (flg ? -2 : 0); 1174 break; 1175 case MAT_UNUSED_NONZERO_LOCATION_ERR: 1176 a->nounused = (flg ? -1 : 0); 1177 break; 1178 case MAT_IGNORE_ZERO_ENTRIES: 1179 a->ignorezeroentries = flg; 1180 break; 1181 case MAT_SPD: 1182 case MAT_SYMMETRIC: 1183 case MAT_STRUCTURALLY_SYMMETRIC: 1184 case MAT_HERMITIAN: 1185 case MAT_SYMMETRY_ETERNAL: 1186 /* These options are handled directly by MatSetOption() */ 1187 break; 1188 case MAT_NEW_DIAGONALS: 1189 case MAT_IGNORE_OFF_PROC_ENTRIES: 1190 case MAT_USE_HASH_TABLE: 1191 ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr); 1192 break; 1193 case MAT_USE_INODES: 1194 /* Not an error because MatSetOption_SeqAIJ_Inode handles this one */ 1195 break; 1196 default: 1197 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op); 1198 } 1199 ierr = MatSetOption_SeqAIJ_Inode(A,op,flg);CHKERRQ(ierr); 1200 PetscFunctionReturn(0); 1201 } 1202 1203 #undef __FUNCT__ 1204 #define __FUNCT__ "MatGetDiagonal_SeqAIJ" 1205 PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v) 1206 { 1207 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1208 PetscErrorCode ierr; 1209 PetscInt i,j,n,*ai=a->i,*aj=a->j,nz; 1210 PetscScalar *aa=a->a,*x,zero=0.0; 1211 1212 PetscFunctionBegin; 1213 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 1214 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 1215 1216 if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) { 1217 PetscInt *diag=a->diag; 1218 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 1219 for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]]; 1220 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 1221 PetscFunctionReturn(0); 1222 } 1223 1224 ierr = VecSet(v,zero);CHKERRQ(ierr); 1225 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 1226 for (i=0; i<n; i++) { 1227 nz = ai[i+1] - ai[i]; 1228 if (!nz) x[i] = 0.0; 1229 for (j=ai[i]; j<ai[i+1]; j++) { 1230 if (aj[j] == i) { 1231 x[i] = aa[j]; 1232 break; 1233 } 1234 } 1235 } 1236 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 1237 PetscFunctionReturn(0); 1238 } 1239 1240 #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 1241 #undef __FUNCT__ 1242 #define __FUNCT__ "MatMultTransposeAdd_SeqAIJ" 1243 PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy) 1244 { 1245 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1246 PetscScalar *y; 1247 const PetscScalar *x; 1248 PetscErrorCode ierr; 1249 PetscInt m = A->rmap->n; 1250 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 1251 const MatScalar *v; 1252 PetscScalar alpha; 1253 PetscInt n,i,j; 1254 const PetscInt *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 = VecGetArrayRead(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 = VecRestoreArrayRead(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 = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr); 1527 1528 aj = a->j; 1529 aa = a->a; 1530 ii = a->i; 1531 if (usecprow) { /* use compressed row format */ 1532 if (zz != yy) { 1533 ierr = PetscMemcpy(z,y,m*sizeof(PetscScalar));CHKERRQ(ierr); 1534 } 1535 m = a->compressedrow.nrows; 1536 ii = a->compressedrow.i; 1537 ridx = a->compressedrow.rindex; 1538 for (i=0; i<m; i++) { 1539 n = ii[i+1] - ii[i]; 1540 aj = a->j + ii[i]; 1541 aa = a->a + ii[i]; 1542 sum = y[*ridx]; 1543 PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1544 z[*ridx++] = sum; 1545 } 1546 } else { /* do not use compressed row format */ 1547 for (i=0; i<m; i++) { 1548 n = ii[i+1] - ii[i]; 1549 aj = a->j + ii[i]; 1550 aa = a->a + ii[i]; 1551 sum = y[i]; 1552 PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1553 z[i] = sum; 1554 } 1555 } 1556 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1557 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1558 ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr); 1559 PetscFunctionReturn(0); 1560 } 1561 1562 #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h> 1563 #undef __FUNCT__ 1564 #define __FUNCT__ "MatMultAdd_SeqAIJ" 1565 PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1566 { 1567 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1568 PetscScalar *y,*z; 1569 const PetscScalar *x; 1570 const MatScalar *aa; 1571 PetscErrorCode ierr; 1572 const PetscInt *aj,*ii,*ridx=NULL; 1573 PetscInt m = A->rmap->n,n,i; 1574 PetscScalar sum; 1575 PetscBool usecprow=a->compressedrow.use; 1576 1577 PetscFunctionBegin; 1578 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 1579 ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr); 1580 1581 aj = a->j; 1582 aa = a->a; 1583 ii = a->i; 1584 if (usecprow) { /* use compressed row format */ 1585 if (zz != yy) { 1586 ierr = PetscMemcpy(z,y,m*sizeof(PetscScalar));CHKERRQ(ierr); 1587 } 1588 m = a->compressedrow.nrows; 1589 ii = a->compressedrow.i; 1590 ridx = a->compressedrow.rindex; 1591 for (i=0; i<m; i++) { 1592 n = ii[i+1] - ii[i]; 1593 aj = a->j + ii[i]; 1594 aa = a->a + ii[i]; 1595 sum = y[*ridx]; 1596 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1597 z[*ridx++] = sum; 1598 } 1599 } else { /* do not use compressed row format */ 1600 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ) 1601 fortranmultaddaij_(&m,x,ii,aj,aa,y,z); 1602 #else 1603 for (i=0; i<m; i++) { 1604 n = ii[i+1] - ii[i]; 1605 aj = a->j + ii[i]; 1606 aa = a->a + ii[i]; 1607 sum = y[i]; 1608 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1609 z[i] = sum; 1610 } 1611 #endif 1612 } 1613 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1614 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1615 ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr); 1616 #if defined(PETSC_HAVE_CUSP) 1617 /* 1618 ierr = VecView(xx,0);CHKERRQ(ierr); 1619 ierr = VecView(zz,0);CHKERRQ(ierr); 1620 ierr = MatView(A,0);CHKERRQ(ierr); 1621 */ 1622 #endif 1623 PetscFunctionReturn(0); 1624 } 1625 1626 /* 1627 Adds diagonal pointers to sparse matrix structure. 1628 */ 1629 #undef __FUNCT__ 1630 #define __FUNCT__ "MatMarkDiagonal_SeqAIJ" 1631 PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A) 1632 { 1633 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1634 PetscErrorCode ierr; 1635 PetscInt i,j,m = A->rmap->n; 1636 1637 PetscFunctionBegin; 1638 if (!a->diag) { 1639 ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr); 1640 ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr); 1641 } 1642 for (i=0; i<A->rmap->n; i++) { 1643 a->diag[i] = a->i[i+1]; 1644 for (j=a->i[i]; j<a->i[i+1]; j++) { 1645 if (a->j[j] == i) { 1646 a->diag[i] = j; 1647 break; 1648 } 1649 } 1650 } 1651 PetscFunctionReturn(0); 1652 } 1653 1654 /* 1655 Checks for missing diagonals 1656 */ 1657 #undef __FUNCT__ 1658 #define __FUNCT__ "MatMissingDiagonal_SeqAIJ" 1659 PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool *missing,PetscInt *d) 1660 { 1661 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1662 PetscInt *diag,*ii = a->i,i; 1663 1664 PetscFunctionBegin; 1665 *missing = PETSC_FALSE; 1666 if (A->rmap->n > 0 && !ii) { 1667 *missing = PETSC_TRUE; 1668 if (d) *d = 0; 1669 PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n"); 1670 } else { 1671 diag = a->diag; 1672 for (i=0; i<A->rmap->n; i++) { 1673 if (diag[i] >= ii[i+1]) { 1674 *missing = PETSC_TRUE; 1675 if (d) *d = i; 1676 PetscInfo1(A,"Matrix is missing diagonal number %D\n",i); 1677 break; 1678 } 1679 } 1680 } 1681 PetscFunctionReturn(0); 1682 } 1683 1684 #undef __FUNCT__ 1685 #define __FUNCT__ "MatInvertDiagonal_SeqAIJ" 1686 PetscErrorCode MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift) 1687 { 1688 Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 1689 PetscErrorCode ierr; 1690 PetscInt i,*diag,m = A->rmap->n; 1691 MatScalar *v = a->a; 1692 PetscScalar *idiag,*mdiag; 1693 1694 PetscFunctionBegin; 1695 if (a->idiagvalid) PetscFunctionReturn(0); 1696 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 1697 diag = a->diag; 1698 if (!a->idiag) { 1699 ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr); 1700 ierr = PetscLogObjectMemory((PetscObject)A, 3*m*sizeof(PetscScalar));CHKERRQ(ierr); 1701 v = a->a; 1702 } 1703 mdiag = a->mdiag; 1704 idiag = a->idiag; 1705 1706 if (omega == 1.0 && !PetscAbsScalar(fshift)) { 1707 for (i=0; i<m; i++) { 1708 mdiag[i] = v[diag[i]]; 1709 if (!PetscAbsScalar(mdiag[i])) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i); 1710 idiag[i] = 1.0/v[diag[i]]; 1711 } 1712 ierr = PetscLogFlops(m);CHKERRQ(ierr); 1713 } else { 1714 for (i=0; i<m; i++) { 1715 mdiag[i] = v[diag[i]]; 1716 idiag[i] = omega/(fshift + v[diag[i]]); 1717 } 1718 ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr); 1719 } 1720 a->idiagvalid = PETSC_TRUE; 1721 PetscFunctionReturn(0); 1722 } 1723 1724 #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h> 1725 #undef __FUNCT__ 1726 #define __FUNCT__ "MatSOR_SeqAIJ" 1727 PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 1728 { 1729 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1730 PetscScalar *x,d,sum,*t,scale; 1731 const MatScalar *v = a->a,*idiag=0,*mdiag; 1732 const PetscScalar *b, *bs,*xb, *ts; 1733 PetscErrorCode ierr; 1734 PetscInt n = A->cmap->n,m = A->rmap->n,i; 1735 const PetscInt *idx,*diag; 1736 1737 PetscFunctionBegin; 1738 its = its*lits; 1739 1740 if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */ 1741 if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);} 1742 a->fshift = fshift; 1743 a->omega = omega; 1744 1745 diag = a->diag; 1746 t = a->ssor_work; 1747 idiag = a->idiag; 1748 mdiag = a->mdiag; 1749 1750 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 1751 ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr); 1752 /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */ 1753 if (flag == SOR_APPLY_UPPER) { 1754 /* apply (U + D/omega) to the vector */ 1755 bs = b; 1756 for (i=0; i<m; i++) { 1757 d = fshift + mdiag[i]; 1758 n = a->i[i+1] - diag[i] - 1; 1759 idx = a->j + diag[i] + 1; 1760 v = a->a + diag[i] + 1; 1761 sum = b[i]*d/omega; 1762 PetscSparseDensePlusDot(sum,bs,v,idx,n); 1763 x[i] = sum; 1764 } 1765 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1766 ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr); 1767 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 1768 PetscFunctionReturn(0); 1769 } 1770 1771 if (flag == SOR_APPLY_LOWER) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented"); 1772 else if (flag & SOR_EISENSTAT) { 1773 /* Let A = L + U + D; where L is lower trianglar, 1774 U is upper triangular, E = D/omega; This routine applies 1775 1776 (L + E)^{-1} A (U + E)^{-1} 1777 1778 to a vector efficiently using Eisenstat's trick. 1779 */ 1780 scale = (2.0/omega) - 1.0; 1781 1782 /* x = (E + U)^{-1} b */ 1783 for (i=m-1; i>=0; i--) { 1784 n = a->i[i+1] - diag[i] - 1; 1785 idx = a->j + diag[i] + 1; 1786 v = a->a + diag[i] + 1; 1787 sum = b[i]; 1788 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1789 x[i] = sum*idiag[i]; 1790 } 1791 1792 /* t = b - (2*E - D)x */ 1793 v = a->a; 1794 for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i]; 1795 1796 /* t = (E + L)^{-1}t */ 1797 ts = t; 1798 diag = a->diag; 1799 for (i=0; i<m; i++) { 1800 n = diag[i] - a->i[i]; 1801 idx = a->j + a->i[i]; 1802 v = a->a + a->i[i]; 1803 sum = t[i]; 1804 PetscSparseDenseMinusDot(sum,ts,v,idx,n); 1805 t[i] = sum*idiag[i]; 1806 /* x = x + t */ 1807 x[i] += t[i]; 1808 } 1809 1810 ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr); 1811 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1812 ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr); 1813 PetscFunctionReturn(0); 1814 } 1815 if (flag & SOR_ZERO_INITIAL_GUESS) { 1816 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 1817 for (i=0; i<m; i++) { 1818 n = diag[i] - a->i[i]; 1819 idx = a->j + a->i[i]; 1820 v = a->a + a->i[i]; 1821 sum = b[i]; 1822 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1823 t[i] = sum; 1824 x[i] = sum*idiag[i]; 1825 } 1826 xb = t; 1827 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 1828 } else xb = b; 1829 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 1830 for (i=m-1; i>=0; i--) { 1831 n = a->i[i+1] - diag[i] - 1; 1832 idx = a->j + diag[i] + 1; 1833 v = a->a + diag[i] + 1; 1834 sum = xb[i]; 1835 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1836 if (xb == b) { 1837 x[i] = sum*idiag[i]; 1838 } else { 1839 x[i] = (1-omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 1840 } 1841 } 1842 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */ 1843 } 1844 its--; 1845 } 1846 while (its--) { 1847 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 1848 for (i=0; i<m; i++) { 1849 /* lower */ 1850 n = diag[i] - a->i[i]; 1851 idx = a->j + a->i[i]; 1852 v = a->a + a->i[i]; 1853 sum = b[i]; 1854 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1855 t[i] = sum; /* save application of the lower-triangular part */ 1856 /* upper */ 1857 n = a->i[i+1] - diag[i] - 1; 1858 idx = a->j + diag[i] + 1; 1859 v = a->a + diag[i] + 1; 1860 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1861 x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 1862 } 1863 xb = t; 1864 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1865 } else xb = b; 1866 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 1867 for (i=m-1; i>=0; i--) { 1868 sum = xb[i]; 1869 if (xb == b) { 1870 /* whole matrix (no checkpointing available) */ 1871 n = a->i[i+1] - a->i[i]; 1872 idx = a->j + a->i[i]; 1873 v = a->a + a->i[i]; 1874 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1875 x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i]; 1876 } else { /* lower-triangular part has been saved, so only apply upper-triangular */ 1877 n = a->i[i+1] - diag[i] - 1; 1878 idx = a->j + diag[i] + 1; 1879 v = a->a + diag[i] + 1; 1880 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1881 x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 1882 } 1883 } 1884 if (xb == b) { 1885 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1886 } else { 1887 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */ 1888 } 1889 } 1890 } 1891 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1892 ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr); 1893 PetscFunctionReturn(0); 1894 } 1895 1896 1897 #undef __FUNCT__ 1898 #define __FUNCT__ "MatGetInfo_SeqAIJ" 1899 PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info) 1900 { 1901 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1902 1903 PetscFunctionBegin; 1904 info->block_size = 1.0; 1905 info->nz_allocated = (double)a->maxnz; 1906 info->nz_used = (double)a->nz; 1907 info->nz_unneeded = (double)(a->maxnz - a->nz); 1908 info->assemblies = (double)A->num_ass; 1909 info->mallocs = (double)A->info.mallocs; 1910 info->memory = ((PetscObject)A)->mem; 1911 if (A->factortype) { 1912 info->fill_ratio_given = A->info.fill_ratio_given; 1913 info->fill_ratio_needed = A->info.fill_ratio_needed; 1914 info->factor_mallocs = A->info.factor_mallocs; 1915 } else { 1916 info->fill_ratio_given = 0; 1917 info->fill_ratio_needed = 0; 1918 info->factor_mallocs = 0; 1919 } 1920 PetscFunctionReturn(0); 1921 } 1922 1923 #undef __FUNCT__ 1924 #define __FUNCT__ "MatZeroRows_SeqAIJ" 1925 PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1926 { 1927 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1928 PetscInt i,m = A->rmap->n - 1,d = 0; 1929 PetscErrorCode ierr; 1930 const PetscScalar *xx; 1931 PetscScalar *bb; 1932 PetscBool missing; 1933 1934 PetscFunctionBegin; 1935 if (x && b) { 1936 ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 1937 ierr = VecGetArray(b,&bb);CHKERRQ(ierr); 1938 for (i=0; i<N; i++) { 1939 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 1940 bb[rows[i]] = diag*xx[rows[i]]; 1941 } 1942 ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 1943 ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr); 1944 } 1945 1946 if (a->keepnonzeropattern) { 1947 for (i=0; i<N; i++) { 1948 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 1949 ierr = PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));CHKERRQ(ierr); 1950 } 1951 if (diag != 0.0) { 1952 ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr); 1953 if (missing) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D",d); 1954 for (i=0; i<N; i++) { 1955 a->a[a->diag[rows[i]]] = diag; 1956 } 1957 } 1958 } else { 1959 if (diag != 0.0) { 1960 for (i=0; i<N; i++) { 1961 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 1962 if (a->ilen[rows[i]] > 0) { 1963 a->ilen[rows[i]] = 1; 1964 a->a[a->i[rows[i]]] = diag; 1965 a->j[a->i[rows[i]]] = rows[i]; 1966 } else { /* in case row was completely empty */ 1967 ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr); 1968 } 1969 } 1970 } else { 1971 for (i=0; i<N; i++) { 1972 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 1973 a->ilen[rows[i]] = 0; 1974 } 1975 } 1976 A->nonzerostate++; 1977 } 1978 ierr = MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1979 PetscFunctionReturn(0); 1980 } 1981 1982 #undef __FUNCT__ 1983 #define __FUNCT__ "MatZeroRowsColumns_SeqAIJ" 1984 PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1985 { 1986 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1987 PetscInt i,j,m = A->rmap->n - 1,d = 0; 1988 PetscErrorCode ierr; 1989 PetscBool missing,*zeroed,vecs = PETSC_FALSE; 1990 const PetscScalar *xx; 1991 PetscScalar *bb; 1992 1993 PetscFunctionBegin; 1994 if (x && b) { 1995 ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 1996 ierr = VecGetArray(b,&bb);CHKERRQ(ierr); 1997 vecs = PETSC_TRUE; 1998 } 1999 ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr); 2000 for (i=0; i<N; i++) { 2001 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 2002 ierr = PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));CHKERRQ(ierr); 2003 2004 zeroed[rows[i]] = PETSC_TRUE; 2005 } 2006 for (i=0; i<A->rmap->n; i++) { 2007 if (!zeroed[i]) { 2008 for (j=a->i[i]; j<a->i[i+1]; j++) { 2009 if (zeroed[a->j[j]]) { 2010 if (vecs) bb[i] -= a->a[j]*xx[a->j[j]]; 2011 a->a[j] = 0.0; 2012 } 2013 } 2014 } else if (vecs) bb[i] = diag*xx[i]; 2015 } 2016 if (x && b) { 2017 ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 2018 ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr); 2019 } 2020 ierr = PetscFree(zeroed);CHKERRQ(ierr); 2021 if (diag != 0.0) { 2022 ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr); 2023 if (missing) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D",d); 2024 for (i=0; i<N; i++) { 2025 a->a[a->diag[rows[i]]] = diag; 2026 } 2027 } 2028 ierr = MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2029 PetscFunctionReturn(0); 2030 } 2031 2032 #undef __FUNCT__ 2033 #define __FUNCT__ "MatGetRow_SeqAIJ" 2034 PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 2035 { 2036 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2037 PetscInt *itmp; 2038 2039 PetscFunctionBegin; 2040 if (row < 0 || row >= A->rmap->n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row); 2041 2042 *nz = a->i[row+1] - a->i[row]; 2043 if (v) *v = a->a + a->i[row]; 2044 if (idx) { 2045 itmp = a->j + a->i[row]; 2046 if (*nz) *idx = itmp; 2047 else *idx = 0; 2048 } 2049 PetscFunctionReturn(0); 2050 } 2051 2052 /* remove this function? */ 2053 #undef __FUNCT__ 2054 #define __FUNCT__ "MatRestoreRow_SeqAIJ" 2055 PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 2056 { 2057 PetscFunctionBegin; 2058 PetscFunctionReturn(0); 2059 } 2060 2061 #undef __FUNCT__ 2062 #define __FUNCT__ "MatNorm_SeqAIJ" 2063 PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm) 2064 { 2065 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2066 MatScalar *v = a->a; 2067 PetscReal sum = 0.0; 2068 PetscErrorCode ierr; 2069 PetscInt i,j; 2070 2071 PetscFunctionBegin; 2072 if (type == NORM_FROBENIUS) { 2073 for (i=0; i<a->nz; i++) { 2074 sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 2075 } 2076 *nrm = PetscSqrtReal(sum); 2077 } else if (type == NORM_1) { 2078 PetscReal *tmp; 2079 PetscInt *jj = a->j; 2080 ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr); 2081 *nrm = 0.0; 2082 for (j=0; j<a->nz; j++) { 2083 tmp[*jj++] += PetscAbsScalar(*v); v++; 2084 } 2085 for (j=0; j<A->cmap->n; j++) { 2086 if (tmp[j] > *nrm) *nrm = tmp[j]; 2087 } 2088 ierr = PetscFree(tmp);CHKERRQ(ierr); 2089 } else if (type == NORM_INFINITY) { 2090 *nrm = 0.0; 2091 for (j=0; j<A->rmap->n; j++) { 2092 v = a->a + a->i[j]; 2093 sum = 0.0; 2094 for (i=0; i<a->i[j+1]-a->i[j]; i++) { 2095 sum += PetscAbsScalar(*v); v++; 2096 } 2097 if (sum > *nrm) *nrm = sum; 2098 } 2099 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm"); 2100 PetscFunctionReturn(0); 2101 } 2102 2103 /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */ 2104 #undef __FUNCT__ 2105 #define __FUNCT__ "MatTransposeSymbolic_SeqAIJ" 2106 PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B) 2107 { 2108 PetscErrorCode ierr; 2109 PetscInt i,j,anzj; 2110 Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data,*b; 2111 PetscInt an=A->cmap->N,am=A->rmap->N; 2112 PetscInt *ati,*atj,*atfill,*ai=a->i,*aj=a->j; 2113 2114 PetscFunctionBegin; 2115 /* Allocate space for symbolic transpose info and work array */ 2116 ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr); 2117 ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr); 2118 ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr); 2119 2120 /* Walk through aj and count ## of non-zeros in each row of A^T. */ 2121 /* Note: offset by 1 for fast conversion into csr format. */ 2122 for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1; 2123 /* Form ati for csr format of A^T. */ 2124 for (i=0;i<an;i++) ati[i+1] += ati[i]; 2125 2126 /* Copy ati into atfill so we have locations of the next free space in atj */ 2127 ierr = PetscMemcpy(atfill,ati,an*sizeof(PetscInt));CHKERRQ(ierr); 2128 2129 /* Walk through A row-wise and mark nonzero entries of A^T. */ 2130 for (i=0;i<am;i++) { 2131 anzj = ai[i+1] - ai[i]; 2132 for (j=0;j<anzj;j++) { 2133 atj[atfill[*aj]] = i; 2134 atfill[*aj++] += 1; 2135 } 2136 } 2137 2138 /* Clean up temporary space and complete requests. */ 2139 ierr = PetscFree(atfill);CHKERRQ(ierr); 2140 ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr); 2141 ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr); 2142 2143 b = (Mat_SeqAIJ*)((*B)->data); 2144 b->free_a = PETSC_FALSE; 2145 b->free_ij = PETSC_TRUE; 2146 b->nonew = 0; 2147 PetscFunctionReturn(0); 2148 } 2149 2150 #undef __FUNCT__ 2151 #define __FUNCT__ "MatTranspose_SeqAIJ" 2152 PetscErrorCode MatTranspose_SeqAIJ(Mat A,MatReuse reuse,Mat *B) 2153 { 2154 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2155 Mat C; 2156 PetscErrorCode ierr; 2157 PetscInt i,*aj = a->j,*ai = a->i,m = A->rmap->n,len,*col; 2158 MatScalar *array = a->a; 2159 2160 PetscFunctionBegin; 2161 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"); 2162 2163 if (reuse == MAT_INITIAL_MATRIX || *B == A) { 2164 ierr = PetscCalloc1(1+A->cmap->n,&col);CHKERRQ(ierr); 2165 2166 for (i=0; i<ai[m]; i++) col[aj[i]] += 1; 2167 ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 2168 ierr = MatSetSizes(C,A->cmap->n,m,A->cmap->n,m);CHKERRQ(ierr); 2169 ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr); 2170 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 2171 ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,col);CHKERRQ(ierr); 2172 ierr = PetscFree(col);CHKERRQ(ierr); 2173 } else { 2174 C = *B; 2175 } 2176 2177 for (i=0; i<m; i++) { 2178 len = ai[i+1]-ai[i]; 2179 ierr = MatSetValues_SeqAIJ(C,len,aj,1,&i,array,INSERT_VALUES);CHKERRQ(ierr); 2180 array += len; 2181 aj += len; 2182 } 2183 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2184 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2185 2186 if (reuse == MAT_INITIAL_MATRIX || *B != A) { 2187 *B = C; 2188 } else { 2189 ierr = MatHeaderMerge(A,C);CHKERRQ(ierr); 2190 } 2191 PetscFunctionReturn(0); 2192 } 2193 2194 #undef __FUNCT__ 2195 #define __FUNCT__ "MatIsTranspose_SeqAIJ" 2196 PetscErrorCode MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f) 2197 { 2198 Mat_SeqAIJ *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) A->data; 2199 PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr; 2200 MatScalar *va,*vb; 2201 PetscErrorCode ierr; 2202 PetscInt ma,na,mb,nb, i; 2203 2204 PetscFunctionBegin; 2205 bij = (Mat_SeqAIJ*) B->data; 2206 2207 ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr); 2208 ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr); 2209 if (ma!=nb || na!=mb) { 2210 *f = PETSC_FALSE; 2211 PetscFunctionReturn(0); 2212 } 2213 aii = aij->i; bii = bij->i; 2214 adx = aij->j; bdx = bij->j; 2215 va = aij->a; vb = bij->a; 2216 ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr); 2217 ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr); 2218 for (i=0; i<ma; i++) aptr[i] = aii[i]; 2219 for (i=0; i<mb; i++) bptr[i] = bii[i]; 2220 2221 *f = PETSC_TRUE; 2222 for (i=0; i<ma; i++) { 2223 while (aptr[i]<aii[i+1]) { 2224 PetscInt idc,idr; 2225 PetscScalar vc,vr; 2226 /* column/row index/value */ 2227 idc = adx[aptr[i]]; 2228 idr = bdx[bptr[idc]]; 2229 vc = va[aptr[i]]; 2230 vr = vb[bptr[idc]]; 2231 if (i!=idr || PetscAbsScalar(vc-vr) > tol) { 2232 *f = PETSC_FALSE; 2233 goto done; 2234 } else { 2235 aptr[i]++; 2236 if (B || i!=idc) bptr[idc]++; 2237 } 2238 } 2239 } 2240 done: 2241 ierr = PetscFree(aptr);CHKERRQ(ierr); 2242 ierr = PetscFree(bptr);CHKERRQ(ierr); 2243 PetscFunctionReturn(0); 2244 } 2245 2246 #undef __FUNCT__ 2247 #define __FUNCT__ "MatIsHermitianTranspose_SeqAIJ" 2248 PetscErrorCode MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f) 2249 { 2250 Mat_SeqAIJ *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) A->data; 2251 PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr; 2252 MatScalar *va,*vb; 2253 PetscErrorCode ierr; 2254 PetscInt ma,na,mb,nb, i; 2255 2256 PetscFunctionBegin; 2257 bij = (Mat_SeqAIJ*) B->data; 2258 2259 ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr); 2260 ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr); 2261 if (ma!=nb || na!=mb) { 2262 *f = PETSC_FALSE; 2263 PetscFunctionReturn(0); 2264 } 2265 aii = aij->i; bii = bij->i; 2266 adx = aij->j; bdx = bij->j; 2267 va = aij->a; vb = bij->a; 2268 ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr); 2269 ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr); 2270 for (i=0; i<ma; i++) aptr[i] = aii[i]; 2271 for (i=0; i<mb; i++) bptr[i] = bii[i]; 2272 2273 *f = PETSC_TRUE; 2274 for (i=0; i<ma; i++) { 2275 while (aptr[i]<aii[i+1]) { 2276 PetscInt idc,idr; 2277 PetscScalar vc,vr; 2278 /* column/row index/value */ 2279 idc = adx[aptr[i]]; 2280 idr = bdx[bptr[idc]]; 2281 vc = va[aptr[i]]; 2282 vr = vb[bptr[idc]]; 2283 if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) { 2284 *f = PETSC_FALSE; 2285 goto done; 2286 } else { 2287 aptr[i]++; 2288 if (B || i!=idc) bptr[idc]++; 2289 } 2290 } 2291 } 2292 done: 2293 ierr = PetscFree(aptr);CHKERRQ(ierr); 2294 ierr = PetscFree(bptr);CHKERRQ(ierr); 2295 PetscFunctionReturn(0); 2296 } 2297 2298 #undef __FUNCT__ 2299 #define __FUNCT__ "MatIsSymmetric_SeqAIJ" 2300 PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool *f) 2301 { 2302 PetscErrorCode ierr; 2303 2304 PetscFunctionBegin; 2305 ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr); 2306 PetscFunctionReturn(0); 2307 } 2308 2309 #undef __FUNCT__ 2310 #define __FUNCT__ "MatIsHermitian_SeqAIJ" 2311 PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool *f) 2312 { 2313 PetscErrorCode ierr; 2314 2315 PetscFunctionBegin; 2316 ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr); 2317 PetscFunctionReturn(0); 2318 } 2319 2320 #undef __FUNCT__ 2321 #define __FUNCT__ "MatDiagonalScale_SeqAIJ" 2322 PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr) 2323 { 2324 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2325 PetscScalar *l,*r,x; 2326 MatScalar *v; 2327 PetscErrorCode ierr; 2328 PetscInt i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz,*jj; 2329 2330 PetscFunctionBegin; 2331 if (ll) { 2332 /* The local size is used so that VecMPI can be passed to this routine 2333 by MatDiagonalScale_MPIAIJ */ 2334 ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr); 2335 if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length"); 2336 ierr = VecGetArray(ll,&l);CHKERRQ(ierr); 2337 v = a->a; 2338 for (i=0; i<m; i++) { 2339 x = l[i]; 2340 M = a->i[i+1] - a->i[i]; 2341 for (j=0; j<M; j++) (*v++) *= x; 2342 } 2343 ierr = VecRestoreArray(ll,&l);CHKERRQ(ierr); 2344 ierr = PetscLogFlops(nz);CHKERRQ(ierr); 2345 } 2346 if (rr) { 2347 ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr); 2348 if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length"); 2349 ierr = VecGetArray(rr,&r);CHKERRQ(ierr); 2350 v = a->a; jj = a->j; 2351 for (i=0; i<nz; i++) (*v++) *= r[*jj++]; 2352 ierr = VecRestoreArray(rr,&r);CHKERRQ(ierr); 2353 ierr = PetscLogFlops(nz);CHKERRQ(ierr); 2354 } 2355 ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr); 2356 PetscFunctionReturn(0); 2357 } 2358 2359 #undef __FUNCT__ 2360 #define __FUNCT__ "MatGetSubMatrix_SeqAIJ" 2361 PetscErrorCode MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B) 2362 { 2363 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*c; 2364 PetscErrorCode ierr; 2365 PetscInt *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens; 2366 PetscInt row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi; 2367 const PetscInt *irow,*icol; 2368 PetscInt nrows,ncols; 2369 PetscInt *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen; 2370 MatScalar *a_new,*mat_a; 2371 Mat C; 2372 PetscBool stride,sorted; 2373 2374 PetscFunctionBegin; 2375 ierr = ISSorted(iscol,&sorted);CHKERRQ(ierr); 2376 if (!sorted) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"IScol is not sorted"); 2377 2378 ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr); 2379 ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr); 2380 ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr); 2381 2382 ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr); 2383 if (stride) { 2384 ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr); 2385 } else { 2386 first = 0; 2387 step = 0; 2388 } 2389 if (stride && step == 1) { 2390 /* special case of contiguous rows */ 2391 ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr); 2392 /* loop over new rows determining lens and starting points */ 2393 for (i=0; i<nrows; i++) { 2394 kstart = ai[irow[i]]; 2395 kend = kstart + ailen[irow[i]]; 2396 starts[i] = kstart; 2397 for (k=kstart; k<kend; k++) { 2398 if (aj[k] >= first) { 2399 starts[i] = k; 2400 break; 2401 } 2402 } 2403 sum = 0; 2404 while (k < kend) { 2405 if (aj[k++] >= first+ncols) break; 2406 sum++; 2407 } 2408 lens[i] = sum; 2409 } 2410 /* create submatrix */ 2411 if (scall == MAT_REUSE_MATRIX) { 2412 PetscInt n_cols,n_rows; 2413 ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr); 2414 if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size"); 2415 ierr = MatZeroEntries(*B);CHKERRQ(ierr); 2416 C = *B; 2417 } else { 2418 PetscInt rbs,cbs; 2419 ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 2420 ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 2421 ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr); 2422 ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr); 2423 ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr); 2424 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 2425 ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr); 2426 } 2427 c = (Mat_SeqAIJ*)C->data; 2428 2429 /* loop over rows inserting into submatrix */ 2430 a_new = c->a; 2431 j_new = c->j; 2432 i_new = c->i; 2433 2434 for (i=0; i<nrows; i++) { 2435 ii = starts[i]; 2436 lensi = lens[i]; 2437 for (k=0; k<lensi; k++) { 2438 *j_new++ = aj[ii+k] - first; 2439 } 2440 ierr = PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(PetscScalar));CHKERRQ(ierr); 2441 a_new += lensi; 2442 i_new[i+1] = i_new[i] + lensi; 2443 c->ilen[i] = lensi; 2444 } 2445 ierr = PetscFree2(lens,starts);CHKERRQ(ierr); 2446 } else { 2447 ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr); 2448 ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr); 2449 ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr); 2450 for (i=0; i<ncols; i++) { 2451 #if defined(PETSC_USE_DEBUG) 2452 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); 2453 #endif 2454 smap[icol[i]] = i+1; 2455 } 2456 2457 /* determine lens of each row */ 2458 for (i=0; i<nrows; i++) { 2459 kstart = ai[irow[i]]; 2460 kend = kstart + a->ilen[irow[i]]; 2461 lens[i] = 0; 2462 for (k=kstart; k<kend; k++) { 2463 if (smap[aj[k]]) { 2464 lens[i]++; 2465 } 2466 } 2467 } 2468 /* Create and fill new matrix */ 2469 if (scall == MAT_REUSE_MATRIX) { 2470 PetscBool equal; 2471 2472 c = (Mat_SeqAIJ*)((*B)->data); 2473 if ((*B)->rmap->n != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size"); 2474 ierr = PetscMemcmp(c->ilen,lens,(*B)->rmap->n*sizeof(PetscInt),&equal);CHKERRQ(ierr); 2475 if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros"); 2476 ierr = PetscMemzero(c->ilen,(*B)->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 2477 C = *B; 2478 } else { 2479 PetscInt rbs,cbs; 2480 ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 2481 ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 2482 ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr); 2483 ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr); 2484 ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr); 2485 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 2486 ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr); 2487 } 2488 c = (Mat_SeqAIJ*)(C->data); 2489 for (i=0; i<nrows; i++) { 2490 row = irow[i]; 2491 kstart = ai[row]; 2492 kend = kstart + a->ilen[row]; 2493 mat_i = c->i[i]; 2494 mat_j = c->j + mat_i; 2495 mat_a = c->a + mat_i; 2496 mat_ilen = c->ilen + i; 2497 for (k=kstart; k<kend; k++) { 2498 if ((tcol=smap[a->j[k]])) { 2499 *mat_j++ = tcol - 1; 2500 *mat_a++ = a->a[k]; 2501 (*mat_ilen)++; 2502 2503 } 2504 } 2505 } 2506 /* Free work space */ 2507 ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr); 2508 ierr = PetscFree(smap);CHKERRQ(ierr); 2509 ierr = PetscFree(lens);CHKERRQ(ierr); 2510 } 2511 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2512 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2513 2514 ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr); 2515 *B = C; 2516 PetscFunctionReturn(0); 2517 } 2518 2519 #undef __FUNCT__ 2520 #define __FUNCT__ "MatGetMultiProcBlock_SeqAIJ" 2521 PetscErrorCode MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat) 2522 { 2523 PetscErrorCode ierr; 2524 Mat B; 2525 2526 PetscFunctionBegin; 2527 if (scall == MAT_INITIAL_MATRIX) { 2528 ierr = MatCreate(subComm,&B);CHKERRQ(ierr); 2529 ierr = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr); 2530 ierr = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr); 2531 ierr = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr); 2532 ierr = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr); 2533 *subMat = B; 2534 } else { 2535 ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 2536 } 2537 PetscFunctionReturn(0); 2538 } 2539 2540 #undef __FUNCT__ 2541 #define __FUNCT__ "MatILUFactor_SeqAIJ" 2542 PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info) 2543 { 2544 Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 2545 PetscErrorCode ierr; 2546 Mat outA; 2547 PetscBool row_identity,col_identity; 2548 2549 PetscFunctionBegin; 2550 if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu"); 2551 2552 ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr); 2553 ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr); 2554 2555 outA = inA; 2556 outA->factortype = MAT_FACTOR_LU; 2557 2558 ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr); 2559 ierr = ISDestroy(&a->row);CHKERRQ(ierr); 2560 2561 a->row = row; 2562 2563 ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr); 2564 ierr = ISDestroy(&a->col);CHKERRQ(ierr); 2565 2566 a->col = col; 2567 2568 /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */ 2569 ierr = ISDestroy(&a->icol);CHKERRQ(ierr); 2570 ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr); 2571 ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr); 2572 2573 if (!a->solve_work) { /* this matrix may have been factored before */ 2574 ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr); 2575 ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr); 2576 } 2577 2578 ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr); 2579 if (row_identity && col_identity) { 2580 ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr); 2581 } else { 2582 ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr); 2583 } 2584 PetscFunctionReturn(0); 2585 } 2586 2587 #undef __FUNCT__ 2588 #define __FUNCT__ "MatScale_SeqAIJ" 2589 PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha) 2590 { 2591 Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 2592 PetscScalar oalpha = alpha; 2593 PetscErrorCode ierr; 2594 PetscBLASInt one = 1,bnz; 2595 2596 PetscFunctionBegin; 2597 ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr); 2598 PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&oalpha,a->a,&one)); 2599 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 2600 ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr); 2601 PetscFunctionReturn(0); 2602 } 2603 2604 #undef __FUNCT__ 2605 #define __FUNCT__ "MatGetSubMatrices_SeqAIJ" 2606 PetscErrorCode MatGetSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[]) 2607 { 2608 PetscErrorCode ierr; 2609 PetscInt i; 2610 2611 PetscFunctionBegin; 2612 if (scall == MAT_INITIAL_MATRIX) { 2613 ierr = PetscMalloc1(n+1,B);CHKERRQ(ierr); 2614 } 2615 2616 for (i=0; i<n; i++) { 2617 ierr = MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr); 2618 } 2619 PetscFunctionReturn(0); 2620 } 2621 2622 #undef __FUNCT__ 2623 #define __FUNCT__ "MatIncreaseOverlap_SeqAIJ" 2624 PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov) 2625 { 2626 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2627 PetscErrorCode ierr; 2628 PetscInt row,i,j,k,l,m,n,*nidx,isz,val; 2629 const PetscInt *idx; 2630 PetscInt start,end,*ai,*aj; 2631 PetscBT table; 2632 2633 PetscFunctionBegin; 2634 m = A->rmap->n; 2635 ai = a->i; 2636 aj = a->j; 2637 2638 if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used"); 2639 2640 ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr); 2641 ierr = PetscBTCreate(m,&table);CHKERRQ(ierr); 2642 2643 for (i=0; i<is_max; i++) { 2644 /* Initialize the two local arrays */ 2645 isz = 0; 2646 ierr = PetscBTMemzero(m,table);CHKERRQ(ierr); 2647 2648 /* Extract the indices, assume there can be duplicate entries */ 2649 ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr); 2650 ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr); 2651 2652 /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 2653 for (j=0; j<n; ++j) { 2654 if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j]; 2655 } 2656 ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr); 2657 ierr = ISDestroy(&is[i]);CHKERRQ(ierr); 2658 2659 k = 0; 2660 for (j=0; j<ov; j++) { /* for each overlap */ 2661 n = isz; 2662 for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */ 2663 row = nidx[k]; 2664 start = ai[row]; 2665 end = ai[row+1]; 2666 for (l = start; l<end; l++) { 2667 val = aj[l]; 2668 if (!PetscBTLookupSet(table,val)) nidx[isz++] = val; 2669 } 2670 } 2671 } 2672 ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr); 2673 } 2674 ierr = PetscBTDestroy(&table);CHKERRQ(ierr); 2675 ierr = PetscFree(nidx);CHKERRQ(ierr); 2676 PetscFunctionReturn(0); 2677 } 2678 2679 /* -------------------------------------------------------------- */ 2680 #undef __FUNCT__ 2681 #define __FUNCT__ "MatPermute_SeqAIJ" 2682 PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B) 2683 { 2684 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2685 PetscErrorCode ierr; 2686 PetscInt i,nz = 0,m = A->rmap->n,n = A->cmap->n; 2687 const PetscInt *row,*col; 2688 PetscInt *cnew,j,*lens; 2689 IS icolp,irowp; 2690 PetscInt *cwork = NULL; 2691 PetscScalar *vwork = NULL; 2692 2693 PetscFunctionBegin; 2694 ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr); 2695 ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr); 2696 ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr); 2697 ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr); 2698 2699 /* determine lengths of permuted rows */ 2700 ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr); 2701 for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i]; 2702 ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr); 2703 ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr); 2704 ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr); 2705 ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr); 2706 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr); 2707 ierr = PetscFree(lens);CHKERRQ(ierr); 2708 2709 ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr); 2710 for (i=0; i<m; i++) { 2711 ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr); 2712 for (j=0; j<nz; j++) cnew[j] = col[cwork[j]]; 2713 ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr); 2714 ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr); 2715 } 2716 ierr = PetscFree(cnew);CHKERRQ(ierr); 2717 2718 (*B)->assembled = PETSC_FALSE; 2719 2720 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2721 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2722 ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr); 2723 ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr); 2724 ierr = ISDestroy(&irowp);CHKERRQ(ierr); 2725 ierr = ISDestroy(&icolp);CHKERRQ(ierr); 2726 PetscFunctionReturn(0); 2727 } 2728 2729 #undef __FUNCT__ 2730 #define __FUNCT__ "MatCopy_SeqAIJ" 2731 PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str) 2732 { 2733 PetscErrorCode ierr; 2734 2735 PetscFunctionBegin; 2736 /* If the two matrices have the same copy implementation, use fast copy. */ 2737 if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) { 2738 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2739 Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 2740 2741 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"); 2742 ierr = PetscMemcpy(b->a,a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));CHKERRQ(ierr); 2743 } else { 2744 ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr); 2745 } 2746 PetscFunctionReturn(0); 2747 } 2748 2749 #undef __FUNCT__ 2750 #define __FUNCT__ "MatSetUp_SeqAIJ" 2751 PetscErrorCode MatSetUp_SeqAIJ(Mat A) 2752 { 2753 PetscErrorCode ierr; 2754 2755 PetscFunctionBegin; 2756 ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,0);CHKERRQ(ierr); 2757 PetscFunctionReturn(0); 2758 } 2759 2760 #undef __FUNCT__ 2761 #define __FUNCT__ "MatSeqAIJGetArray_SeqAIJ" 2762 PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[]) 2763 { 2764 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2765 2766 PetscFunctionBegin; 2767 *array = a->a; 2768 PetscFunctionReturn(0); 2769 } 2770 2771 #undef __FUNCT__ 2772 #define __FUNCT__ "MatSeqAIJRestoreArray_SeqAIJ" 2773 PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[]) 2774 { 2775 PetscFunctionBegin; 2776 PetscFunctionReturn(0); 2777 } 2778 2779 /* 2780 Computes the number of nonzeros per row needed for preallocation when X and Y 2781 have different nonzero structure. 2782 */ 2783 #undef __FUNCT__ 2784 #define __FUNCT__ "MatAXPYGetPreallocation_SeqX_private" 2785 PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz) 2786 { 2787 PetscInt i,j,k,nzx,nzy; 2788 2789 PetscFunctionBegin; 2790 /* Set the number of nonzeros in the new matrix */ 2791 for (i=0; i<m; i++) { 2792 const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i]; 2793 nzx = xi[i+1] - xi[i]; 2794 nzy = yi[i+1] - yi[i]; 2795 nnz[i] = 0; 2796 for (j=0,k=0; j<nzx; j++) { /* Point in X */ 2797 for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */ 2798 if (k<nzy && yjj[k]==xjj[j]) k++; /* Skip duplicate */ 2799 nnz[i]++; 2800 } 2801 for (; k<nzy; k++) nnz[i]++; 2802 } 2803 PetscFunctionReturn(0); 2804 } 2805 2806 #undef __FUNCT__ 2807 #define __FUNCT__ "MatAXPYGetPreallocation_SeqAIJ" 2808 PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz) 2809 { 2810 PetscInt m = Y->rmap->N; 2811 Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data; 2812 Mat_SeqAIJ *y = (Mat_SeqAIJ*)Y->data; 2813 PetscErrorCode ierr; 2814 2815 PetscFunctionBegin; 2816 /* Set the number of nonzeros in the new matrix */ 2817 ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr); 2818 PetscFunctionReturn(0); 2819 } 2820 2821 #undef __FUNCT__ 2822 #define __FUNCT__ "MatAXPY_SeqAIJ" 2823 PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str) 2824 { 2825 PetscErrorCode ierr; 2826 Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data; 2827 PetscBLASInt one=1,bnz; 2828 2829 PetscFunctionBegin; 2830 ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr); 2831 if (str == SAME_NONZERO_PATTERN) { 2832 PetscScalar alpha = a; 2833 PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one)); 2834 ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr); 2835 ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr); 2836 } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 2837 ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr); 2838 } else { 2839 Mat B; 2840 PetscInt *nnz; 2841 ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr); 2842 ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr); 2843 ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr); 2844 ierr = MatSetSizes(B,Y->rmap->n,Y->cmap->n,Y->rmap->N,Y->cmap->N);CHKERRQ(ierr); 2845 ierr = MatSetBlockSizesFromMats(B,Y,Y);CHKERRQ(ierr); 2846 ierr = MatSetType(B,(MatType) ((PetscObject)Y)->type_name);CHKERRQ(ierr); 2847 ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr); 2848 ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr); 2849 ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr); 2850 ierr = MatHeaderReplace(Y,B);CHKERRQ(ierr); 2851 ierr = PetscFree(nnz);CHKERRQ(ierr); 2852 } 2853 PetscFunctionReturn(0); 2854 } 2855 2856 #undef __FUNCT__ 2857 #define __FUNCT__ "MatConjugate_SeqAIJ" 2858 PetscErrorCode MatConjugate_SeqAIJ(Mat mat) 2859 { 2860 #if defined(PETSC_USE_COMPLEX) 2861 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 2862 PetscInt i,nz; 2863 PetscScalar *a; 2864 2865 PetscFunctionBegin; 2866 nz = aij->nz; 2867 a = aij->a; 2868 for (i=0; i<nz; i++) a[i] = PetscConj(a[i]); 2869 #else 2870 PetscFunctionBegin; 2871 #endif 2872 PetscFunctionReturn(0); 2873 } 2874 2875 #undef __FUNCT__ 2876 #define __FUNCT__ "MatGetRowMaxAbs_SeqAIJ" 2877 PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2878 { 2879 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2880 PetscErrorCode ierr; 2881 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2882 PetscReal atmp; 2883 PetscScalar *x; 2884 MatScalar *aa; 2885 2886 PetscFunctionBegin; 2887 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2888 aa = a->a; 2889 ai = a->i; 2890 aj = a->j; 2891 2892 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2893 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2894 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 2895 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2896 for (i=0; i<m; i++) { 2897 ncols = ai[1] - ai[0]; ai++; 2898 x[i] = 0.0; 2899 for (j=0; j<ncols; j++) { 2900 atmp = PetscAbsScalar(*aa); 2901 if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;} 2902 aa++; aj++; 2903 } 2904 } 2905 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2906 PetscFunctionReturn(0); 2907 } 2908 2909 #undef __FUNCT__ 2910 #define __FUNCT__ "MatGetRowMax_SeqAIJ" 2911 PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2912 { 2913 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2914 PetscErrorCode ierr; 2915 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2916 PetscScalar *x; 2917 MatScalar *aa; 2918 2919 PetscFunctionBegin; 2920 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2921 aa = a->a; 2922 ai = a->i; 2923 aj = a->j; 2924 2925 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2926 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2927 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 2928 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2929 for (i=0; i<m; i++) { 2930 ncols = ai[1] - ai[0]; ai++; 2931 if (ncols == A->cmap->n) { /* row is dense */ 2932 x[i] = *aa; if (idx) idx[i] = 0; 2933 } else { /* row is sparse so already KNOW maximum is 0.0 or higher */ 2934 x[i] = 0.0; 2935 if (idx) { 2936 idx[i] = 0; /* in case ncols is zero */ 2937 for (j=0;j<ncols;j++) { /* find first implicit 0.0 in the row */ 2938 if (aj[j] > j) { 2939 idx[i] = j; 2940 break; 2941 } 2942 } 2943 } 2944 } 2945 for (j=0; j<ncols; j++) { 2946 if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 2947 aa++; aj++; 2948 } 2949 } 2950 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2951 PetscFunctionReturn(0); 2952 } 2953 2954 #undef __FUNCT__ 2955 #define __FUNCT__ "MatGetRowMinAbs_SeqAIJ" 2956 PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2957 { 2958 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2959 PetscErrorCode ierr; 2960 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2961 PetscReal atmp; 2962 PetscScalar *x; 2963 MatScalar *aa; 2964 2965 PetscFunctionBegin; 2966 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2967 aa = a->a; 2968 ai = a->i; 2969 aj = a->j; 2970 2971 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2972 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2973 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 2974 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); 2975 for (i=0; i<m; i++) { 2976 ncols = ai[1] - ai[0]; ai++; 2977 if (ncols) { 2978 /* Get first nonzero */ 2979 for (j = 0; j < ncols; j++) { 2980 atmp = PetscAbsScalar(aa[j]); 2981 if (atmp > 1.0e-12) { 2982 x[i] = atmp; 2983 if (idx) idx[i] = aj[j]; 2984 break; 2985 } 2986 } 2987 if (j == ncols) {x[i] = PetscAbsScalar(*aa); if (idx) idx[i] = *aj;} 2988 } else { 2989 x[i] = 0.0; if (idx) idx[i] = 0; 2990 } 2991 for (j = 0; j < ncols; j++) { 2992 atmp = PetscAbsScalar(*aa); 2993 if (atmp > 1.0e-12 && PetscAbsScalar(x[i]) > atmp) {x[i] = atmp; if (idx) idx[i] = *aj;} 2994 aa++; aj++; 2995 } 2996 } 2997 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2998 PetscFunctionReturn(0); 2999 } 3000 3001 #undef __FUNCT__ 3002 #define __FUNCT__ "MatGetRowMin_SeqAIJ" 3003 PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3004 { 3005 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3006 PetscErrorCode ierr; 3007 PetscInt i,j,m = A->rmap->n,ncols,n; 3008 const PetscInt *ai,*aj; 3009 PetscScalar *x; 3010 const MatScalar *aa; 3011 3012 PetscFunctionBegin; 3013 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3014 aa = a->a; 3015 ai = a->i; 3016 aj = a->j; 3017 3018 ierr = VecSet(v,0.0);CHKERRQ(ierr); 3019 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 3020 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 3021 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 3022 for (i=0; i<m; i++) { 3023 ncols = ai[1] - ai[0]; ai++; 3024 if (ncols == A->cmap->n) { /* row is dense */ 3025 x[i] = *aa; if (idx) idx[i] = 0; 3026 } else { /* row is sparse so already KNOW minimum is 0.0 or lower */ 3027 x[i] = 0.0; 3028 if (idx) { /* find first implicit 0.0 in the row */ 3029 idx[i] = 0; /* in case ncols is zero */ 3030 for (j=0; j<ncols; j++) { 3031 if (aj[j] > j) { 3032 idx[i] = j; 3033 break; 3034 } 3035 } 3036 } 3037 } 3038 for (j=0; j<ncols; j++) { 3039 if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 3040 aa++; aj++; 3041 } 3042 } 3043 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 3044 PetscFunctionReturn(0); 3045 } 3046 3047 #include <petscblaslapack.h> 3048 #include <petsc-private/kernels/blockinvert.h> 3049 3050 #undef __FUNCT__ 3051 #define __FUNCT__ "MatInvertBlockDiagonal_SeqAIJ" 3052 PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values) 3053 { 3054 Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 3055 PetscErrorCode ierr; 3056 PetscInt i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j; 3057 MatScalar *diag,work[25],*v_work; 3058 PetscReal shift = 0.0; 3059 3060 PetscFunctionBegin; 3061 if (a->ibdiagvalid) { 3062 if (values) *values = a->ibdiag; 3063 PetscFunctionReturn(0); 3064 } 3065 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 3066 if (!a->ibdiag) { 3067 ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr); 3068 ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr); 3069 } 3070 diag = a->ibdiag; 3071 if (values) *values = a->ibdiag; 3072 /* factor and invert each block */ 3073 switch (bs) { 3074 case 1: 3075 for (i=0; i<mbs; i++) { 3076 ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr); 3077 diag[i] = (PetscScalar)1.0 / (diag[i] + shift); 3078 } 3079 break; 3080 case 2: 3081 for (i=0; i<mbs; i++) { 3082 ij[0] = 2*i; ij[1] = 2*i + 1; 3083 ierr = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr); 3084 ierr = PetscKernel_A_gets_inverse_A_2(diag,shift);CHKERRQ(ierr); 3085 ierr = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr); 3086 diag += 4; 3087 } 3088 break; 3089 case 3: 3090 for (i=0; i<mbs; i++) { 3091 ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2; 3092 ierr = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr); 3093 ierr = PetscKernel_A_gets_inverse_A_3(diag,shift);CHKERRQ(ierr); 3094 ierr = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr); 3095 diag += 9; 3096 } 3097 break; 3098 case 4: 3099 for (i=0; i<mbs; i++) { 3100 ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3; 3101 ierr = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr); 3102 ierr = PetscKernel_A_gets_inverse_A_4(diag,shift);CHKERRQ(ierr); 3103 ierr = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr); 3104 diag += 16; 3105 } 3106 break; 3107 case 5: 3108 for (i=0; i<mbs; i++) { 3109 ij[0] = 5*i; ij[1] = 5*i + 1; ij[2] = 5*i + 2; ij[3] = 5*i + 3; ij[4] = 5*i + 4; 3110 ierr = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr); 3111 ierr = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift);CHKERRQ(ierr); 3112 ierr = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr); 3113 diag += 25; 3114 } 3115 break; 3116 case 6: 3117 for (i=0; i<mbs; i++) { 3118 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; 3119 ierr = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr); 3120 ierr = PetscKernel_A_gets_inverse_A_6(diag,shift);CHKERRQ(ierr); 3121 ierr = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr); 3122 diag += 36; 3123 } 3124 break; 3125 case 7: 3126 for (i=0; i<mbs; i++) { 3127 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; 3128 ierr = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr); 3129 ierr = PetscKernel_A_gets_inverse_A_7(diag,shift);CHKERRQ(ierr); 3130 ierr = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr); 3131 diag += 49; 3132 } 3133 break; 3134 default: 3135 ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr); 3136 for (i=0; i<mbs; i++) { 3137 for (j=0; j<bs; j++) { 3138 IJ[j] = bs*i + j; 3139 } 3140 ierr = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr); 3141 ierr = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work);CHKERRQ(ierr); 3142 ierr = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr); 3143 diag += bs2; 3144 } 3145 ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr); 3146 } 3147 a->ibdiagvalid = PETSC_TRUE; 3148 PetscFunctionReturn(0); 3149 } 3150 3151 #undef __FUNCT__ 3152 #define __FUNCT__ "MatSetRandom_SeqAIJ" 3153 static PetscErrorCode MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx) 3154 { 3155 PetscErrorCode ierr; 3156 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)x->data; 3157 PetscScalar a; 3158 PetscInt m,n,i,j,col; 3159 3160 PetscFunctionBegin; 3161 if (!x->assembled) { 3162 ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr); 3163 for (i=0; i<m; i++) { 3164 for (j=0; j<aij->imax[i]; j++) { 3165 ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr); 3166 col = (PetscInt)(n*PetscRealPart(a)); 3167 ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr); 3168 } 3169 } 3170 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet coded"); 3171 ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3172 ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3173 PetscFunctionReturn(0); 3174 } 3175 3176 /* -------------------------------------------------------------------*/ 3177 static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ, 3178 MatGetRow_SeqAIJ, 3179 MatRestoreRow_SeqAIJ, 3180 MatMult_SeqAIJ, 3181 /* 4*/ MatMultAdd_SeqAIJ, 3182 MatMultTranspose_SeqAIJ, 3183 MatMultTransposeAdd_SeqAIJ, 3184 0, 3185 0, 3186 0, 3187 /* 10*/ 0, 3188 MatLUFactor_SeqAIJ, 3189 0, 3190 MatSOR_SeqAIJ, 3191 MatTranspose_SeqAIJ, 3192 /*1 5*/ MatGetInfo_SeqAIJ, 3193 MatEqual_SeqAIJ, 3194 MatGetDiagonal_SeqAIJ, 3195 MatDiagonalScale_SeqAIJ, 3196 MatNorm_SeqAIJ, 3197 /* 20*/ 0, 3198 MatAssemblyEnd_SeqAIJ, 3199 MatSetOption_SeqAIJ, 3200 MatZeroEntries_SeqAIJ, 3201 /* 24*/ MatZeroRows_SeqAIJ, 3202 0, 3203 0, 3204 0, 3205 0, 3206 /* 29*/ MatSetUp_SeqAIJ, 3207 0, 3208 0, 3209 0, 3210 0, 3211 /* 34*/ MatDuplicate_SeqAIJ, 3212 0, 3213 0, 3214 MatILUFactor_SeqAIJ, 3215 0, 3216 /* 39*/ MatAXPY_SeqAIJ, 3217 MatGetSubMatrices_SeqAIJ, 3218 MatIncreaseOverlap_SeqAIJ, 3219 MatGetValues_SeqAIJ, 3220 MatCopy_SeqAIJ, 3221 /* 44*/ MatGetRowMax_SeqAIJ, 3222 MatScale_SeqAIJ, 3223 0, 3224 MatDiagonalSet_SeqAIJ, 3225 MatZeroRowsColumns_SeqAIJ, 3226 /* 49*/ MatSetRandom_SeqAIJ, 3227 MatGetRowIJ_SeqAIJ, 3228 MatRestoreRowIJ_SeqAIJ, 3229 MatGetColumnIJ_SeqAIJ, 3230 MatRestoreColumnIJ_SeqAIJ, 3231 /* 54*/ MatFDColoringCreate_SeqXAIJ, 3232 0, 3233 0, 3234 MatPermute_SeqAIJ, 3235 0, 3236 /* 59*/ 0, 3237 MatDestroy_SeqAIJ, 3238 MatView_SeqAIJ, 3239 0, 3240 MatMatMatMult_SeqAIJ_SeqAIJ_SeqAIJ, 3241 /* 64*/ MatMatMatMultSymbolic_SeqAIJ_SeqAIJ_SeqAIJ, 3242 MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ, 3243 0, 3244 0, 3245 0, 3246 /* 69*/ MatGetRowMaxAbs_SeqAIJ, 3247 MatGetRowMinAbs_SeqAIJ, 3248 0, 3249 MatSetColoring_SeqAIJ, 3250 0, 3251 /* 74*/ MatSetValuesAdifor_SeqAIJ, 3252 MatFDColoringApply_AIJ, 3253 0, 3254 0, 3255 0, 3256 /* 79*/ MatFindZeroDiagonals_SeqAIJ, 3257 0, 3258 0, 3259 0, 3260 MatLoad_SeqAIJ, 3261 /* 84*/ MatIsSymmetric_SeqAIJ, 3262 MatIsHermitian_SeqAIJ, 3263 0, 3264 0, 3265 0, 3266 /* 89*/ MatMatMult_SeqAIJ_SeqAIJ, 3267 MatMatMultSymbolic_SeqAIJ_SeqAIJ, 3268 MatMatMultNumeric_SeqAIJ_SeqAIJ, 3269 MatPtAP_SeqAIJ_SeqAIJ, 3270 MatPtAPSymbolic_SeqAIJ_SeqAIJ_DenseAxpy, 3271 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ, 3272 MatMatTransposeMult_SeqAIJ_SeqAIJ, 3273 MatMatTransposeMultSymbolic_SeqAIJ_SeqAIJ, 3274 MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ, 3275 0, 3276 /* 99*/ 0, 3277 0, 3278 0, 3279 MatConjugate_SeqAIJ, 3280 0, 3281 /*104*/ MatSetValuesRow_SeqAIJ, 3282 MatRealPart_SeqAIJ, 3283 MatImaginaryPart_SeqAIJ, 3284 0, 3285 0, 3286 /*109*/ MatMatSolve_SeqAIJ, 3287 0, 3288 MatGetRowMin_SeqAIJ, 3289 0, 3290 MatMissingDiagonal_SeqAIJ, 3291 /*114*/ 0, 3292 0, 3293 0, 3294 0, 3295 0, 3296 /*119*/ 0, 3297 0, 3298 0, 3299 0, 3300 MatGetMultiProcBlock_SeqAIJ, 3301 /*124*/ MatFindNonzeroRows_SeqAIJ, 3302 MatGetColumnNorms_SeqAIJ, 3303 MatInvertBlockDiagonal_SeqAIJ, 3304 0, 3305 0, 3306 /*129*/ 0, 3307 MatTransposeMatMult_SeqAIJ_SeqAIJ, 3308 MatTransposeMatMultSymbolic_SeqAIJ_SeqAIJ, 3309 MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ, 3310 MatTransposeColoringCreate_SeqAIJ, 3311 /*134*/ MatTransColoringApplySpToDen_SeqAIJ, 3312 MatTransColoringApplyDenToSp_SeqAIJ, 3313 MatRARt_SeqAIJ_SeqAIJ, 3314 MatRARtSymbolic_SeqAIJ_SeqAIJ, 3315 MatRARtNumeric_SeqAIJ_SeqAIJ, 3316 /*139*/0, 3317 0, 3318 0, 3319 MatFDColoringSetUp_SeqXAIJ, 3320 MatFindOffBlockDiagonalEntries_SeqAIJ, 3321 /*144*/MatCreateMPIMatConcatenateSeqMat_SeqAIJ 3322 }; 3323 3324 #undef __FUNCT__ 3325 #define __FUNCT__ "MatSeqAIJSetColumnIndices_SeqAIJ" 3326 PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices) 3327 { 3328 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3329 PetscInt i,nz,n; 3330 3331 PetscFunctionBegin; 3332 nz = aij->maxnz; 3333 n = mat->rmap->n; 3334 for (i=0; i<nz; i++) { 3335 aij->j[i] = indices[i]; 3336 } 3337 aij->nz = nz; 3338 for (i=0; i<n; i++) { 3339 aij->ilen[i] = aij->imax[i]; 3340 } 3341 PetscFunctionReturn(0); 3342 } 3343 3344 #undef __FUNCT__ 3345 #define __FUNCT__ "MatSeqAIJSetColumnIndices" 3346 /*@ 3347 MatSeqAIJSetColumnIndices - Set the column indices for all the rows 3348 in the matrix. 3349 3350 Input Parameters: 3351 + mat - the SeqAIJ matrix 3352 - indices - the column indices 3353 3354 Level: advanced 3355 3356 Notes: 3357 This can be called if you have precomputed the nonzero structure of the 3358 matrix and want to provide it to the matrix object to improve the performance 3359 of the MatSetValues() operation. 3360 3361 You MUST have set the correct numbers of nonzeros per row in the call to 3362 MatCreateSeqAIJ(), and the columns indices MUST be sorted. 3363 3364 MUST be called before any calls to MatSetValues(); 3365 3366 The indices should start with zero, not one. 3367 3368 @*/ 3369 PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices) 3370 { 3371 PetscErrorCode ierr; 3372 3373 PetscFunctionBegin; 3374 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3375 PetscValidPointer(indices,2); 3376 ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr); 3377 PetscFunctionReturn(0); 3378 } 3379 3380 /* ----------------------------------------------------------------------------------------*/ 3381 3382 #undef __FUNCT__ 3383 #define __FUNCT__ "MatStoreValues_SeqAIJ" 3384 PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) 3385 { 3386 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3387 PetscErrorCode ierr; 3388 size_t nz = aij->i[mat->rmap->n]; 3389 3390 PetscFunctionBegin; 3391 if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3392 3393 /* allocate space for values if not already there */ 3394 if (!aij->saved_values) { 3395 ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr); 3396 ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr); 3397 } 3398 3399 /* copy values over */ 3400 ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr); 3401 PetscFunctionReturn(0); 3402 } 3403 3404 #undef __FUNCT__ 3405 #define __FUNCT__ "MatStoreValues" 3406 /*@ 3407 MatStoreValues - Stashes a copy of the matrix values; this allows, for 3408 example, reuse of the linear part of a Jacobian, while recomputing the 3409 nonlinear portion. 3410 3411 Collect on Mat 3412 3413 Input Parameters: 3414 . mat - the matrix (currently only AIJ matrices support this option) 3415 3416 Level: advanced 3417 3418 Common Usage, with SNESSolve(): 3419 $ Create Jacobian matrix 3420 $ Set linear terms into matrix 3421 $ Apply boundary conditions to matrix, at this time matrix must have 3422 $ final nonzero structure (i.e. setting the nonlinear terms and applying 3423 $ boundary conditions again will not change the nonzero structure 3424 $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3425 $ ierr = MatStoreValues(mat); 3426 $ Call SNESSetJacobian() with matrix 3427 $ In your Jacobian routine 3428 $ ierr = MatRetrieveValues(mat); 3429 $ Set nonlinear terms in matrix 3430 3431 Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself: 3432 $ // build linear portion of Jacobian 3433 $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3434 $ ierr = MatStoreValues(mat); 3435 $ loop over nonlinear iterations 3436 $ ierr = MatRetrieveValues(mat); 3437 $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian 3438 $ // call MatAssemblyBegin/End() on matrix 3439 $ Solve linear system with Jacobian 3440 $ endloop 3441 3442 Notes: 3443 Matrix must already be assemblied before calling this routine 3444 Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before 3445 calling this routine. 3446 3447 When this is called multiple times it overwrites the previous set of stored values 3448 and does not allocated additional space. 3449 3450 .seealso: MatRetrieveValues() 3451 3452 @*/ 3453 PetscErrorCode MatStoreValues(Mat mat) 3454 { 3455 PetscErrorCode ierr; 3456 3457 PetscFunctionBegin; 3458 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3459 if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 3460 if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3461 ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr); 3462 PetscFunctionReturn(0); 3463 } 3464 3465 #undef __FUNCT__ 3466 #define __FUNCT__ "MatRetrieveValues_SeqAIJ" 3467 PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat) 3468 { 3469 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3470 PetscErrorCode ierr; 3471 PetscInt nz = aij->i[mat->rmap->n]; 3472 3473 PetscFunctionBegin; 3474 if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3475 if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first"); 3476 /* copy values over */ 3477 ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr); 3478 PetscFunctionReturn(0); 3479 } 3480 3481 #undef __FUNCT__ 3482 #define __FUNCT__ "MatRetrieveValues" 3483 /*@ 3484 MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 3485 example, reuse of the linear part of a Jacobian, while recomputing the 3486 nonlinear portion. 3487 3488 Collect on Mat 3489 3490 Input Parameters: 3491 . mat - the matrix (currently on AIJ matrices support this option) 3492 3493 Level: advanced 3494 3495 .seealso: MatStoreValues() 3496 3497 @*/ 3498 PetscErrorCode MatRetrieveValues(Mat mat) 3499 { 3500 PetscErrorCode ierr; 3501 3502 PetscFunctionBegin; 3503 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3504 if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 3505 if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3506 ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr); 3507 PetscFunctionReturn(0); 3508 } 3509 3510 3511 /* --------------------------------------------------------------------------------*/ 3512 #undef __FUNCT__ 3513 #define __FUNCT__ "MatCreateSeqAIJ" 3514 /*@C 3515 MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format 3516 (the default parallel PETSc format). For good matrix assembly performance 3517 the user should preallocate the matrix storage by setting the parameter nz 3518 (or the array nnz). By setting these parameters accurately, performance 3519 during matrix assembly can be increased by more than a factor of 50. 3520 3521 Collective on MPI_Comm 3522 3523 Input Parameters: 3524 + comm - MPI communicator, set to PETSC_COMM_SELF 3525 . m - number of rows 3526 . n - number of columns 3527 . nz - number of nonzeros per row (same for all rows) 3528 - nnz - array containing the number of nonzeros in the various rows 3529 (possibly different for each row) or NULL 3530 3531 Output Parameter: 3532 . A - the matrix 3533 3534 It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 3535 MatXXXXSetPreallocation() paradgm instead of this routine directly. 3536 [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 3537 3538 Notes: 3539 If nnz is given then nz is ignored 3540 3541 The AIJ format (also called the Yale sparse matrix format or 3542 compressed row storage), is fully compatible with standard Fortran 77 3543 storage. That is, the stored row and column indices can begin at 3544 either one (as in Fortran) or zero. See the users' manual for details. 3545 3546 Specify the preallocated storage with either nz or nnz (not both). 3547 Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 3548 allocation. For large problems you MUST preallocate memory or you 3549 will get TERRIBLE performance, see the users' manual chapter on matrices. 3550 3551 By default, this format uses inodes (identical nodes) when possible, to 3552 improve numerical efficiency of matrix-vector products and solves. We 3553 search for consecutive rows with the same nonzero structure, thereby 3554 reusing matrix information to achieve increased efficiency. 3555 3556 Options Database Keys: 3557 + -mat_no_inode - Do not use inodes 3558 - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3559 3560 Level: intermediate 3561 3562 .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays() 3563 3564 @*/ 3565 PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A) 3566 { 3567 PetscErrorCode ierr; 3568 3569 PetscFunctionBegin; 3570 ierr = MatCreate(comm,A);CHKERRQ(ierr); 3571 ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr); 3572 ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr); 3573 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr); 3574 PetscFunctionReturn(0); 3575 } 3576 3577 #undef __FUNCT__ 3578 #define __FUNCT__ "MatSeqAIJSetPreallocation" 3579 /*@C 3580 MatSeqAIJSetPreallocation - For good matrix assembly performance 3581 the user should preallocate the matrix storage by setting the parameter nz 3582 (or the array nnz). By setting these parameters accurately, performance 3583 during matrix assembly can be increased by more than a factor of 50. 3584 3585 Collective on MPI_Comm 3586 3587 Input Parameters: 3588 + B - The matrix 3589 . nz - number of nonzeros per row (same for all rows) 3590 - nnz - array containing the number of nonzeros in the various rows 3591 (possibly different for each row) or NULL 3592 3593 Notes: 3594 If nnz is given then nz is ignored 3595 3596 The AIJ format (also called the Yale sparse matrix format or 3597 compressed row storage), is fully compatible with standard Fortran 77 3598 storage. That is, the stored row and column indices can begin at 3599 either one (as in Fortran) or zero. See the users' manual for details. 3600 3601 Specify the preallocated storage with either nz or nnz (not both). 3602 Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 3603 allocation. For large problems you MUST preallocate memory or you 3604 will get TERRIBLE performance, see the users' manual chapter on matrices. 3605 3606 You can call MatGetInfo() to get information on how effective the preallocation was; 3607 for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 3608 You can also run with the option -info and look for messages with the string 3609 malloc in them to see if additional memory allocation was needed. 3610 3611 Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix 3612 entries or columns indices 3613 3614 By default, this format uses inodes (identical nodes) when possible, to 3615 improve numerical efficiency of matrix-vector products and solves. We 3616 search for consecutive rows with the same nonzero structure, thereby 3617 reusing matrix information to achieve increased efficiency. 3618 3619 Options Database Keys: 3620 + -mat_no_inode - Do not use inodes 3621 . -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3622 - -mat_aij_oneindex - Internally use indexing starting at 1 3623 rather than 0. Note that when calling MatSetValues(), 3624 the user still MUST index entries starting at 0! 3625 3626 Level: intermediate 3627 3628 .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo() 3629 3630 @*/ 3631 PetscErrorCode MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[]) 3632 { 3633 PetscErrorCode ierr; 3634 3635 PetscFunctionBegin; 3636 PetscValidHeaderSpecific(B,MAT_CLASSID,1); 3637 PetscValidType(B,1); 3638 ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr); 3639 PetscFunctionReturn(0); 3640 } 3641 3642 #undef __FUNCT__ 3643 #define __FUNCT__ "MatSeqAIJSetPreallocation_SeqAIJ" 3644 PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz) 3645 { 3646 Mat_SeqAIJ *b; 3647 PetscBool skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE; 3648 PetscErrorCode ierr; 3649 PetscInt i; 3650 3651 PetscFunctionBegin; 3652 if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 3653 if (nz == MAT_SKIP_ALLOCATION) { 3654 skipallocation = PETSC_TRUE; 3655 nz = 0; 3656 } 3657 3658 ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 3659 ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 3660 3661 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 3662 if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz); 3663 if (nnz) { 3664 for (i=0; i<B->rmap->n; i++) { 3665 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]); 3666 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); 3667 } 3668 } 3669 3670 B->preallocated = PETSC_TRUE; 3671 3672 b = (Mat_SeqAIJ*)B->data; 3673 3674 if (!skipallocation) { 3675 if (!b->imax) { 3676 ierr = PetscMalloc2(B->rmap->n,&b->imax,B->rmap->n,&b->ilen);CHKERRQ(ierr); 3677 ierr = PetscLogObjectMemory((PetscObject)B,2*B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 3678 } 3679 if (!nnz) { 3680 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 3681 else if (nz < 0) nz = 1; 3682 for (i=0; i<B->rmap->n; i++) b->imax[i] = nz; 3683 nz = nz*B->rmap->n; 3684 } else { 3685 nz = 0; 3686 for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz += nnz[i];} 3687 } 3688 /* b->ilen will count nonzeros in each row so far. */ 3689 for (i=0; i<B->rmap->n; i++) b->ilen[i] = 0; 3690 3691 /* allocate the matrix space */ 3692 ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr); 3693 ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr); 3694 ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr); 3695 b->i[0] = 0; 3696 for (i=1; i<B->rmap->n+1; i++) { 3697 b->i[i] = b->i[i-1] + b->imax[i-1]; 3698 } 3699 b->singlemalloc = PETSC_TRUE; 3700 b->free_a = PETSC_TRUE; 3701 b->free_ij = PETSC_TRUE; 3702 #if defined(PETSC_THREADCOMM_ACTIVE) 3703 ierr = MatZeroEntries_SeqAIJ(B);CHKERRQ(ierr); 3704 #endif 3705 } else { 3706 b->free_a = PETSC_FALSE; 3707 b->free_ij = PETSC_FALSE; 3708 } 3709 3710 b->nz = 0; 3711 b->maxnz = nz; 3712 B->info.nz_unneeded = (double)b->maxnz; 3713 if (realalloc) { 3714 ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 3715 } 3716 PetscFunctionReturn(0); 3717 } 3718 3719 #undef __FUNCT__ 3720 #define __FUNCT__ "MatSeqAIJSetPreallocationCSR" 3721 /*@ 3722 MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format. 3723 3724 Input Parameters: 3725 + B - the matrix 3726 . i - the indices into j for the start of each row (starts with zero) 3727 . j - the column indices for each row (starts with zero) these must be sorted for each row 3728 - v - optional values in the matrix 3729 3730 Level: developer 3731 3732 The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays() 3733 3734 .keywords: matrix, aij, compressed row, sparse, sequential 3735 3736 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), SeqAIJ 3737 @*/ 3738 PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[]) 3739 { 3740 PetscErrorCode ierr; 3741 3742 PetscFunctionBegin; 3743 PetscValidHeaderSpecific(B,MAT_CLASSID,1); 3744 PetscValidType(B,1); 3745 ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr); 3746 PetscFunctionReturn(0); 3747 } 3748 3749 #undef __FUNCT__ 3750 #define __FUNCT__ "MatSeqAIJSetPreallocationCSR_SeqAIJ" 3751 PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[]) 3752 { 3753 PetscInt i; 3754 PetscInt m,n; 3755 PetscInt nz; 3756 PetscInt *nnz, nz_max = 0; 3757 PetscScalar *values; 3758 PetscErrorCode ierr; 3759 3760 PetscFunctionBegin; 3761 if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]); 3762 3763 ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 3764 ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 3765 3766 ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr); 3767 ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr); 3768 for (i = 0; i < m; i++) { 3769 nz = Ii[i+1]- Ii[i]; 3770 nz_max = PetscMax(nz_max, nz); 3771 if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz); 3772 nnz[i] = nz; 3773 } 3774 ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr); 3775 ierr = PetscFree(nnz);CHKERRQ(ierr); 3776 3777 if (v) { 3778 values = (PetscScalar*) v; 3779 } else { 3780 ierr = PetscCalloc1(nz_max, &values);CHKERRQ(ierr); 3781 } 3782 3783 for (i = 0; i < m; i++) { 3784 nz = Ii[i+1] - Ii[i]; 3785 ierr = MatSetValues_SeqAIJ(B, 1, &i, nz, J+Ii[i], values + (v ? Ii[i] : 0), INSERT_VALUES);CHKERRQ(ierr); 3786 } 3787 3788 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3789 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3790 3791 if (!v) { 3792 ierr = PetscFree(values);CHKERRQ(ierr); 3793 } 3794 ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 3795 PetscFunctionReturn(0); 3796 } 3797 3798 #include <../src/mat/impls/dense/seq/dense.h> 3799 #include <petsc-private/kernels/petscaxpy.h> 3800 3801 #undef __FUNCT__ 3802 #define __FUNCT__ "MatMatMultNumeric_SeqDense_SeqAIJ" 3803 /* 3804 Computes (B'*A')' since computing B*A directly is untenable 3805 3806 n p p 3807 ( ) ( ) ( ) 3808 m ( A ) * n ( B ) = m ( C ) 3809 ( ) ( ) ( ) 3810 3811 */ 3812 PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C) 3813 { 3814 PetscErrorCode ierr; 3815 Mat_SeqDense *sub_a = (Mat_SeqDense*)A->data; 3816 Mat_SeqAIJ *sub_b = (Mat_SeqAIJ*)B->data; 3817 Mat_SeqDense *sub_c = (Mat_SeqDense*)C->data; 3818 PetscInt i,n,m,q,p; 3819 const PetscInt *ii,*idx; 3820 const PetscScalar *b,*a,*a_q; 3821 PetscScalar *c,*c_q; 3822 3823 PetscFunctionBegin; 3824 m = A->rmap->n; 3825 n = A->cmap->n; 3826 p = B->cmap->n; 3827 a = sub_a->v; 3828 b = sub_b->a; 3829 c = sub_c->v; 3830 ierr = PetscMemzero(c,m*p*sizeof(PetscScalar));CHKERRQ(ierr); 3831 3832 ii = sub_b->i; 3833 idx = sub_b->j; 3834 for (i=0; i<n; i++) { 3835 q = ii[i+1] - ii[i]; 3836 while (q-->0) { 3837 c_q = c + m*(*idx); 3838 a_q = a + m*i; 3839 PetscKernelAXPY(c_q,*b,a_q,m); 3840 idx++; 3841 b++; 3842 } 3843 } 3844 PetscFunctionReturn(0); 3845 } 3846 3847 #undef __FUNCT__ 3848 #define __FUNCT__ "MatMatMultSymbolic_SeqDense_SeqAIJ" 3849 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat *C) 3850 { 3851 PetscErrorCode ierr; 3852 PetscInt m=A->rmap->n,n=B->cmap->n; 3853 Mat Cmat; 3854 3855 PetscFunctionBegin; 3856 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); 3857 ierr = MatCreate(PetscObjectComm((PetscObject)A),&Cmat);CHKERRQ(ierr); 3858 ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr); 3859 ierr = MatSetBlockSizesFromMats(Cmat,A,B);CHKERRQ(ierr); 3860 ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr); 3861 ierr = MatSeqDenseSetPreallocation(Cmat,NULL);CHKERRQ(ierr); 3862 3863 Cmat->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ; 3864 3865 *C = Cmat; 3866 PetscFunctionReturn(0); 3867 } 3868 3869 /* ----------------------------------------------------------------*/ 3870 #undef __FUNCT__ 3871 #define __FUNCT__ "MatMatMult_SeqDense_SeqAIJ" 3872 PetscErrorCode MatMatMult_SeqDense_SeqAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 3873 { 3874 PetscErrorCode ierr; 3875 3876 PetscFunctionBegin; 3877 if (scall == MAT_INITIAL_MATRIX) { 3878 ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 3879 ierr = MatMatMultSymbolic_SeqDense_SeqAIJ(A,B,fill,C);CHKERRQ(ierr); 3880 ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 3881 } 3882 ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 3883 ierr = MatMatMultNumeric_SeqDense_SeqAIJ(A,B,*C);CHKERRQ(ierr); 3884 ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 3885 PetscFunctionReturn(0); 3886 } 3887 3888 3889 /*MC 3890 MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 3891 based on compressed sparse row format. 3892 3893 Options Database Keys: 3894 . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 3895 3896 Level: beginner 3897 3898 .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType 3899 M*/ 3900 3901 /*MC 3902 MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 3903 3904 This matrix type is identical to MATSEQAIJ when constructed with a single process communicator, 3905 and MATMPIAIJ otherwise. As a result, for single process communicators, 3906 MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation is supported 3907 for communicators controlling multiple processes. It is recommended that you call both of 3908 the above preallocation routines for simplicity. 3909 3910 Options Database Keys: 3911 . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions() 3912 3913 Developer Notes: Subclasses include MATAIJCUSP, MATAIJPERM, MATAIJCRL, and also automatically switches over to use inodes when 3914 enough exist. 3915 3916 Level: beginner 3917 3918 .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ 3919 M*/ 3920 3921 /*MC 3922 MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 3923 3924 This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator, 3925 and MATMPIAIJCRL otherwise. As a result, for single process communicators, 3926 MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 3927 for communicators controlling multiple processes. It is recommended that you call both of 3928 the above preallocation routines for simplicity. 3929 3930 Options Database Keys: 3931 . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions() 3932 3933 Level: beginner 3934 3935 .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL 3936 M*/ 3937 3938 PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*); 3939 #if defined(PETSC_HAVE_ELEMENTAL) 3940 PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*); 3941 #endif 3942 3943 #if defined(PETSC_HAVE_MATLAB_ENGINE) 3944 PETSC_EXTERN PetscErrorCode MatlabEnginePut_SeqAIJ(PetscObject,void*); 3945 PETSC_EXTERN PetscErrorCode MatlabEngineGet_SeqAIJ(PetscObject,void*); 3946 #endif 3947 3948 3949 #undef __FUNCT__ 3950 #define __FUNCT__ "MatSeqAIJGetArray" 3951 /*@C 3952 MatSeqAIJGetArray - gives access to the array where the data for a SeqSeqAIJ matrix is stored 3953 3954 Not Collective 3955 3956 Input Parameter: 3957 . mat - a MATSEQAIJ matrix 3958 3959 Output Parameter: 3960 . array - pointer to the data 3961 3962 Level: intermediate 3963 3964 .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90() 3965 @*/ 3966 PetscErrorCode MatSeqAIJGetArray(Mat A,PetscScalar **array) 3967 { 3968 PetscErrorCode ierr; 3969 3970 PetscFunctionBegin; 3971 ierr = PetscUseMethod(A,"MatSeqAIJGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr); 3972 PetscFunctionReturn(0); 3973 } 3974 3975 #undef __FUNCT__ 3976 #define __FUNCT__ "MatSeqAIJGetMaxRowNonzeros" 3977 /*@C 3978 MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row 3979 3980 Not Collective 3981 3982 Input Parameter: 3983 . mat - a MATSEQAIJ matrix 3984 3985 Output Parameter: 3986 . nz - the maximum number of nonzeros in any row 3987 3988 Level: intermediate 3989 3990 .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90() 3991 @*/ 3992 PetscErrorCode MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz) 3993 { 3994 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 3995 3996 PetscFunctionBegin; 3997 *nz = aij->rmax; 3998 PetscFunctionReturn(0); 3999 } 4000 4001 #undef __FUNCT__ 4002 #define __FUNCT__ "MatSeqAIJRestoreArray" 4003 /*@C 4004 MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray() 4005 4006 Not Collective 4007 4008 Input Parameters: 4009 . mat - a MATSEQAIJ matrix 4010 . array - pointer to the data 4011 4012 Level: intermediate 4013 4014 .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90() 4015 @*/ 4016 PetscErrorCode MatSeqAIJRestoreArray(Mat A,PetscScalar **array) 4017 { 4018 PetscErrorCode ierr; 4019 4020 PetscFunctionBegin; 4021 ierr = PetscUseMethod(A,"MatSeqAIJRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr); 4022 PetscFunctionReturn(0); 4023 } 4024 4025 #undef __FUNCT__ 4026 #define __FUNCT__ "MatCreate_SeqAIJ" 4027 PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B) 4028 { 4029 Mat_SeqAIJ *b; 4030 PetscErrorCode ierr; 4031 PetscMPIInt size; 4032 4033 PetscFunctionBegin; 4034 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr); 4035 if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1"); 4036 4037 ierr = PetscNewLog(B,&b);CHKERRQ(ierr); 4038 4039 B->data = (void*)b; 4040 4041 ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 4042 4043 b->row = 0; 4044 b->col = 0; 4045 b->icol = 0; 4046 b->reallocs = 0; 4047 b->ignorezeroentries = PETSC_FALSE; 4048 b->roworiented = PETSC_TRUE; 4049 b->nonew = 0; 4050 b->diag = 0; 4051 b->solve_work = 0; 4052 B->spptr = 0; 4053 b->saved_values = 0; 4054 b->idiag = 0; 4055 b->mdiag = 0; 4056 b->ssor_work = 0; 4057 b->omega = 1.0; 4058 b->fshift = 0.0; 4059 b->idiagvalid = PETSC_FALSE; 4060 b->ibdiagvalid = PETSC_FALSE; 4061 b->keepnonzeropattern = PETSC_FALSE; 4062 4063 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 4064 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJGetArray_C",MatSeqAIJGetArray_SeqAIJ);CHKERRQ(ierr); 4065 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJRestoreArray_C",MatSeqAIJRestoreArray_SeqAIJ);CHKERRQ(ierr); 4066 4067 #if defined(PETSC_HAVE_MATLAB_ENGINE) 4068 ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr); 4069 ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr); 4070 #endif 4071 4072 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr); 4073 ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr); 4074 ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr); 4075 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr); 4076 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr); 4077 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr); 4078 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr); 4079 #if defined(PETSC_HAVE_ELEMENTAL) 4080 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr); 4081 #endif 4082 ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr); 4083 ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr); 4084 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr); 4085 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr); 4086 ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr); 4087 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqdense_seqaij_C",MatMatMult_SeqDense_SeqAIJ);CHKERRQ(ierr); 4088 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaij_C",MatMatMultSymbolic_SeqDense_SeqAIJ);CHKERRQ(ierr); 4089 ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqdense_seqaij_C",MatMatMultNumeric_SeqDense_SeqAIJ);CHKERRQ(ierr); 4090 ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr); 4091 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 4092 PetscFunctionReturn(0); 4093 } 4094 4095 #undef __FUNCT__ 4096 #define __FUNCT__ "MatDuplicateNoCreate_SeqAIJ" 4097 /* 4098 Given a matrix generated with MatGetFactor() duplicates all the information in A into B 4099 */ 4100 PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace) 4101 { 4102 Mat_SeqAIJ *c,*a = (Mat_SeqAIJ*)A->data; 4103 PetscErrorCode ierr; 4104 PetscInt i,m = A->rmap->n; 4105 4106 PetscFunctionBegin; 4107 c = (Mat_SeqAIJ*)C->data; 4108 4109 C->factortype = A->factortype; 4110 c->row = 0; 4111 c->col = 0; 4112 c->icol = 0; 4113 c->reallocs = 0; 4114 4115 C->assembled = PETSC_TRUE; 4116 4117 ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr); 4118 ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr); 4119 4120 ierr = PetscMalloc2(m,&c->imax,m,&c->ilen);CHKERRQ(ierr); 4121 ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr); 4122 for (i=0; i<m; i++) { 4123 c->imax[i] = a->imax[i]; 4124 c->ilen[i] = a->ilen[i]; 4125 } 4126 4127 /* allocate the matrix space */ 4128 if (mallocmatspace) { 4129 ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr); 4130 ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 4131 4132 c->singlemalloc = PETSC_TRUE; 4133 4134 ierr = PetscMemcpy(c->i,a->i,(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 4135 if (m > 0) { 4136 ierr = PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(PetscInt));CHKERRQ(ierr); 4137 if (cpvalues == MAT_COPY_VALUES) { 4138 ierr = PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr); 4139 } else { 4140 ierr = PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr); 4141 } 4142 } 4143 } 4144 4145 c->ignorezeroentries = a->ignorezeroentries; 4146 c->roworiented = a->roworiented; 4147 c->nonew = a->nonew; 4148 if (a->diag) { 4149 ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr); 4150 ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 4151 for (i=0; i<m; i++) { 4152 c->diag[i] = a->diag[i]; 4153 } 4154 } else c->diag = 0; 4155 4156 c->solve_work = 0; 4157 c->saved_values = 0; 4158 c->idiag = 0; 4159 c->ssor_work = 0; 4160 c->keepnonzeropattern = a->keepnonzeropattern; 4161 c->free_a = PETSC_TRUE; 4162 c->free_ij = PETSC_TRUE; 4163 4164 c->rmax = a->rmax; 4165 c->nz = a->nz; 4166 c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 4167 C->preallocated = PETSC_TRUE; 4168 4169 c->compressedrow.use = a->compressedrow.use; 4170 c->compressedrow.nrows = a->compressedrow.nrows; 4171 if (a->compressedrow.use) { 4172 i = a->compressedrow.nrows; 4173 ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr); 4174 ierr = PetscMemcpy(c->compressedrow.i,a->compressedrow.i,(i+1)*sizeof(PetscInt));CHKERRQ(ierr); 4175 ierr = PetscMemcpy(c->compressedrow.rindex,a->compressedrow.rindex,i*sizeof(PetscInt));CHKERRQ(ierr); 4176 } else { 4177 c->compressedrow.use = PETSC_FALSE; 4178 c->compressedrow.i = NULL; 4179 c->compressedrow.rindex = NULL; 4180 } 4181 C->nonzerostate = A->nonzerostate; 4182 4183 ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr); 4184 ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr); 4185 PetscFunctionReturn(0); 4186 } 4187 4188 #undef __FUNCT__ 4189 #define __FUNCT__ "MatDuplicate_SeqAIJ" 4190 PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B) 4191 { 4192 PetscErrorCode ierr; 4193 4194 PetscFunctionBegin; 4195 ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr); 4196 ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr); 4197 if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) { 4198 ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr); 4199 } 4200 ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr); 4201 ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr); 4202 PetscFunctionReturn(0); 4203 } 4204 4205 #undef __FUNCT__ 4206 #define __FUNCT__ "MatLoad_SeqAIJ" 4207 PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer) 4208 { 4209 Mat_SeqAIJ *a; 4210 PetscErrorCode ierr; 4211 PetscInt i,sum,nz,header[4],*rowlengths = 0,M,N,rows,cols; 4212 int fd; 4213 PetscMPIInt size; 4214 MPI_Comm comm; 4215 PetscInt bs = newMat->rmap->bs; 4216 4217 PetscFunctionBegin; 4218 /* force binary viewer to load .info file if it has not yet done so */ 4219 ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr); 4220 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 4221 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 4222 if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"view must have one processor"); 4223 4224 ierr = PetscOptionsBegin(comm,NULL,"Options for loading SEQAIJ matrix","Mat");CHKERRQ(ierr); 4225 ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,NULL);CHKERRQ(ierr); 4226 ierr = PetscOptionsEnd();CHKERRQ(ierr); 4227 if (bs < 0) bs = 1; 4228 ierr = MatSetBlockSize(newMat,bs);CHKERRQ(ierr); 4229 4230 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 4231 ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr); 4232 if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file"); 4233 M = header[1]; N = header[2]; nz = header[3]; 4234 4235 if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ"); 4236 4237 /* read in row lengths */ 4238 ierr = PetscMalloc1(M,&rowlengths);CHKERRQ(ierr); 4239 ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr); 4240 4241 /* check if sum of rowlengths is same as nz */ 4242 for (i=0,sum=0; i< M; i++) sum +=rowlengths[i]; 4243 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); 4244 4245 /* set global size if not set already*/ 4246 if (newMat->rmap->n < 0 && newMat->rmap->N < 0 && newMat->cmap->n < 0 && newMat->cmap->N < 0) { 4247 ierr = MatSetSizes(newMat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 4248 } else { 4249 /* if sizes and type are already set, check if the vector global sizes are correct */ 4250 ierr = MatGetSize(newMat,&rows,&cols);CHKERRQ(ierr); 4251 if (rows < 0 && cols < 0) { /* user might provide local size instead of global size */ 4252 ierr = MatGetLocalSize(newMat,&rows,&cols);CHKERRQ(ierr); 4253 } 4254 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); 4255 } 4256 ierr = MatSeqAIJSetPreallocation_SeqAIJ(newMat,0,rowlengths);CHKERRQ(ierr); 4257 a = (Mat_SeqAIJ*)newMat->data; 4258 4259 ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT);CHKERRQ(ierr); 4260 4261 /* read in nonzero values */ 4262 ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);CHKERRQ(ierr); 4263 4264 /* set matrix "i" values */ 4265 a->i[0] = 0; 4266 for (i=1; i<= M; i++) { 4267 a->i[i] = a->i[i-1] + rowlengths[i-1]; 4268 a->ilen[i-1] = rowlengths[i-1]; 4269 } 4270 ierr = PetscFree(rowlengths);CHKERRQ(ierr); 4271 4272 ierr = MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4273 ierr = MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4274 PetscFunctionReturn(0); 4275 } 4276 4277 #undef __FUNCT__ 4278 #define __FUNCT__ "MatEqual_SeqAIJ" 4279 PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg) 4280 { 4281 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data; 4282 PetscErrorCode ierr; 4283 #if defined(PETSC_USE_COMPLEX) 4284 PetscInt k; 4285 #endif 4286 4287 PetscFunctionBegin; 4288 /* If the matrix dimensions are not equal,or no of nonzeros */ 4289 if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) { 4290 *flg = PETSC_FALSE; 4291 PetscFunctionReturn(0); 4292 } 4293 4294 /* if the a->i are the same */ 4295 ierr = PetscMemcmp(a->i,b->i,(A->rmap->n+1)*sizeof(PetscInt),flg);CHKERRQ(ierr); 4296 if (!*flg) PetscFunctionReturn(0); 4297 4298 /* if a->j are the same */ 4299 ierr = PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),flg);CHKERRQ(ierr); 4300 if (!*flg) PetscFunctionReturn(0); 4301 4302 /* if a->a are the same */ 4303 #if defined(PETSC_USE_COMPLEX) 4304 for (k=0; k<a->nz; k++) { 4305 if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])) { 4306 *flg = PETSC_FALSE; 4307 PetscFunctionReturn(0); 4308 } 4309 } 4310 #else 4311 ierr = PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);CHKERRQ(ierr); 4312 #endif 4313 PetscFunctionReturn(0); 4314 } 4315 4316 #undef __FUNCT__ 4317 #define __FUNCT__ "MatCreateSeqAIJWithArrays" 4318 /*@ 4319 MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format) 4320 provided by the user. 4321 4322 Collective on MPI_Comm 4323 4324 Input Parameters: 4325 + comm - must be an MPI communicator of size 1 4326 . m - number of rows 4327 . n - number of columns 4328 . i - row indices 4329 . j - column indices 4330 - a - matrix values 4331 4332 Output Parameter: 4333 . mat - the matrix 4334 4335 Level: intermediate 4336 4337 Notes: 4338 The i, j, and a arrays are not copied by this routine, the user must free these arrays 4339 once the matrix is destroyed and not before 4340 4341 You cannot set new nonzero locations into this matrix, that will generate an error. 4342 4343 The i and j indices are 0 based 4344 4345 The format which is used for the sparse matrix input, is equivalent to a 4346 row-major ordering.. i.e for the following matrix, the input data expected is 4347 as shown: 4348 4349 1 0 0 4350 2 0 3 4351 4 5 6 4352 4353 i = {0,1,3,6} [size = nrow+1 = 3+1] 4354 j = {0,0,2,0,1,2} [size = nz = 6]; values must be sorted for each row 4355 v = {1,2,3,4,5,6} [size = nz = 6] 4356 4357 4358 .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR() 4359 4360 @*/ 4361 PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt *i,PetscInt *j,PetscScalar *a,Mat *mat) 4362 { 4363 PetscErrorCode ierr; 4364 PetscInt ii; 4365 Mat_SeqAIJ *aij; 4366 #if defined(PETSC_USE_DEBUG) 4367 PetscInt jj; 4368 #endif 4369 4370 PetscFunctionBegin; 4371 if (i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 4372 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 4373 ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr); 4374 /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */ 4375 ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr); 4376 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr); 4377 aij = (Mat_SeqAIJ*)(*mat)->data; 4378 ierr = PetscMalloc2(m,&aij->imax,m,&aij->ilen);CHKERRQ(ierr); 4379 4380 aij->i = i; 4381 aij->j = j; 4382 aij->a = a; 4383 aij->singlemalloc = PETSC_FALSE; 4384 aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 4385 aij->free_a = PETSC_FALSE; 4386 aij->free_ij = PETSC_FALSE; 4387 4388 for (ii=0; ii<m; ii++) { 4389 aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii]; 4390 #if defined(PETSC_USE_DEBUG) 4391 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]); 4392 for (jj=i[ii]+1; jj<i[ii+1]; jj++) { 4393 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); 4394 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); 4395 } 4396 #endif 4397 } 4398 #if defined(PETSC_USE_DEBUG) 4399 for (ii=0; ii<aij->i[m]; ii++) { 4400 if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]); 4401 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]); 4402 } 4403 #endif 4404 4405 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4406 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4407 PetscFunctionReturn(0); 4408 } 4409 #undef __FUNCT__ 4410 #define __FUNCT__ "MatCreateSeqAIJFromTriple" 4411 /*@C 4412 MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format) 4413 provided by the user. 4414 4415 Collective on MPI_Comm 4416 4417 Input Parameters: 4418 + comm - must be an MPI communicator of size 1 4419 . m - number of rows 4420 . n - number of columns 4421 . i - row indices 4422 . j - column indices 4423 . a - matrix values 4424 . nz - number of nonzeros 4425 - idx - 0 or 1 based 4426 4427 Output Parameter: 4428 . mat - the matrix 4429 4430 Level: intermediate 4431 4432 Notes: 4433 The i and j indices are 0 based 4434 4435 The format which is used for the sparse matrix input, is equivalent to a 4436 row-major ordering.. i.e for the following matrix, the input data expected is 4437 as shown: 4438 4439 1 0 0 4440 2 0 3 4441 4 5 6 4442 4443 i = {0,1,1,2,2,2} 4444 j = {0,0,2,0,1,2} 4445 v = {1,2,3,4,5,6} 4446 4447 4448 .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR() 4449 4450 @*/ 4451 PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt *i,PetscInt *j,PetscScalar *a,Mat *mat,PetscInt nz,PetscBool idx) 4452 { 4453 PetscErrorCode ierr; 4454 PetscInt ii, *nnz, one = 1,row,col; 4455 4456 4457 PetscFunctionBegin; 4458 ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr); 4459 for (ii = 0; ii < nz; ii++) { 4460 nnz[i[ii] - !!idx] += 1; 4461 } 4462 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 4463 ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr); 4464 ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr); 4465 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr); 4466 for (ii = 0; ii < nz; ii++) { 4467 if (idx) { 4468 row = i[ii] - 1; 4469 col = j[ii] - 1; 4470 } else { 4471 row = i[ii]; 4472 col = j[ii]; 4473 } 4474 ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr); 4475 } 4476 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4477 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4478 ierr = PetscFree(nnz);CHKERRQ(ierr); 4479 PetscFunctionReturn(0); 4480 } 4481 4482 #undef __FUNCT__ 4483 #define __FUNCT__ "MatSetColoring_SeqAIJ" 4484 PetscErrorCode MatSetColoring_SeqAIJ(Mat A,ISColoring coloring) 4485 { 4486 PetscErrorCode ierr; 4487 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 4488 4489 PetscFunctionBegin; 4490 if (coloring->ctype == IS_COLORING_GLOBAL) { 4491 ierr = ISColoringReference(coloring);CHKERRQ(ierr); 4492 a->coloring = coloring; 4493 } else if (coloring->ctype == IS_COLORING_GHOSTED) { 4494 PetscInt i,*larray; 4495 ISColoring ocoloring; 4496 ISColoringValue *colors; 4497 4498 /* set coloring for diagonal portion */ 4499 ierr = PetscMalloc1(A->cmap->n,&larray);CHKERRQ(ierr); 4500 for (i=0; i<A->cmap->n; i++) larray[i] = i; 4501 ierr = ISGlobalToLocalMappingApply(A->cmap->mapping,IS_GTOLM_MASK,A->cmap->n,larray,NULL,larray);CHKERRQ(ierr); 4502 ierr = PetscMalloc1(A->cmap->n,&colors);CHKERRQ(ierr); 4503 for (i=0; i<A->cmap->n; i++) colors[i] = coloring->colors[larray[i]]; 4504 ierr = PetscFree(larray);CHKERRQ(ierr); 4505 ierr = ISColoringCreate(PETSC_COMM_SELF,coloring->n,A->cmap->n,colors,PETSC_OWN_POINTER,&ocoloring);CHKERRQ(ierr); 4506 a->coloring = ocoloring; 4507 } 4508 PetscFunctionReturn(0); 4509 } 4510 4511 #undef __FUNCT__ 4512 #define __FUNCT__ "MatSetValuesAdifor_SeqAIJ" 4513 PetscErrorCode MatSetValuesAdifor_SeqAIJ(Mat A,PetscInt nl,void *advalues) 4514 { 4515 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 4516 PetscInt m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j; 4517 MatScalar *v = a->a; 4518 PetscScalar *values = (PetscScalar*)advalues; 4519 ISColoringValue *color; 4520 4521 PetscFunctionBegin; 4522 if (!a->coloring) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix"); 4523 color = a->coloring->colors; 4524 /* loop over rows */ 4525 for (i=0; i<m; i++) { 4526 nz = ii[i+1] - ii[i]; 4527 /* loop over columns putting computed value into matrix */ 4528 for (j=0; j<nz; j++) *v++ = values[color[*jj++]]; 4529 values += nl; /* jump to next row of derivatives */ 4530 } 4531 PetscFunctionReturn(0); 4532 } 4533 4534 #undef __FUNCT__ 4535 #define __FUNCT__ "MatSeqAIJInvalidateDiagonal" 4536 PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A) 4537 { 4538 Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data; 4539 PetscErrorCode ierr; 4540 4541 PetscFunctionBegin; 4542 a->idiagvalid = PETSC_FALSE; 4543 a->ibdiagvalid = PETSC_FALSE; 4544 4545 ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr); 4546 PetscFunctionReturn(0); 4547 } 4548 4549 #undef __FUNCT__ 4550 #define __FUNCT__ "MatCreateMPIMatConcatenateSeqMat_SeqAIJ" 4551 PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat) 4552 { 4553 PetscErrorCode ierr; 4554 4555 PetscFunctionBegin; 4556 ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr); 4557 PetscFunctionReturn(0); 4558 } 4559 4560 /* 4561 Special version for direct calls from Fortran 4562 */ 4563 #include <petsc-private/fortranimpl.h> 4564 #if defined(PETSC_HAVE_FORTRAN_CAPS) 4565 #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ 4566 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 4567 #define matsetvaluesseqaij_ matsetvaluesseqaij 4568 #endif 4569 4570 /* Change these macros so can be used in void function */ 4571 #undef CHKERRQ 4572 #define CHKERRQ(ierr) CHKERRABORT(PetscObjectComm((PetscObject)A),ierr) 4573 #undef SETERRQ2 4574 #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr) 4575 #undef SETERRQ3 4576 #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr) 4577 4578 #undef __FUNCT__ 4579 #define __FUNCT__ "matsetvaluesseqaij_" 4580 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) 4581 { 4582 Mat A = *AA; 4583 PetscInt m = *mm, n = *nn; 4584 InsertMode is = *isis; 4585 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 4586 PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N; 4587 PetscInt *imax,*ai,*ailen; 4588 PetscErrorCode ierr; 4589 PetscInt *aj,nonew = a->nonew,lastcol = -1; 4590 MatScalar *ap,value,*aa; 4591 PetscBool ignorezeroentries = a->ignorezeroentries; 4592 PetscBool roworiented = a->roworiented; 4593 4594 PetscFunctionBegin; 4595 MatCheckPreallocated(A,1); 4596 imax = a->imax; 4597 ai = a->i; 4598 ailen = a->ilen; 4599 aj = a->j; 4600 aa = a->a; 4601 4602 for (k=0; k<m; k++) { /* loop over added rows */ 4603 row = im[k]; 4604 if (row < 0) continue; 4605 #if defined(PETSC_USE_DEBUG) 4606 if (row >= A->rmap->n) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large"); 4607 #endif 4608 rp = aj + ai[row]; ap = aa + ai[row]; 4609 rmax = imax[row]; nrow = ailen[row]; 4610 low = 0; 4611 high = nrow; 4612 for (l=0; l<n; l++) { /* loop over added columns */ 4613 if (in[l] < 0) continue; 4614 #if defined(PETSC_USE_DEBUG) 4615 if (in[l] >= A->cmap->n) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large"); 4616 #endif 4617 col = in[l]; 4618 if (roworiented) value = v[l + k*n]; 4619 else value = v[k + l*m]; 4620 4621 if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 4622 4623 if (col <= lastcol) low = 0; 4624 else high = nrow; 4625 lastcol = col; 4626 while (high-low > 5) { 4627 t = (low+high)/2; 4628 if (rp[t] > col) high = t; 4629 else low = t; 4630 } 4631 for (i=low; i<high; i++) { 4632 if (rp[i] > col) break; 4633 if (rp[i] == col) { 4634 if (is == ADD_VALUES) ap[i] += value; 4635 else ap[i] = value; 4636 goto noinsert; 4637 } 4638 } 4639 if (value == 0.0 && ignorezeroentries) goto noinsert; 4640 if (nonew == 1) goto noinsert; 4641 if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix"); 4642 MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar); 4643 N = nrow++ - 1; a->nz++; high++; 4644 /* shift up all the later entries in this row */ 4645 for (ii=N; ii>=i; ii--) { 4646 rp[ii+1] = rp[ii]; 4647 ap[ii+1] = ap[ii]; 4648 } 4649 rp[i] = col; 4650 ap[i] = value; 4651 A->nonzerostate++; 4652 noinsert:; 4653 low = i + 1; 4654 } 4655 ailen[row] = nrow; 4656 } 4657 PetscFunctionReturnVoid(); 4658 } 4659 4660