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