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