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