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 ierr = PetscFree(a->perm);CHKERRQ(ierr); 1275 ierr = PetscFree(a->jmap);CHKERRQ(ierr); 1276 ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr); 1277 ierr = PetscFree(A->data);CHKERRQ(ierr); 1278 1279 /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this. 1280 That function is so heavily used (sometimes in an hidden way through multnumeric function pointers) 1281 that is hard to properly add this data to the MatProduct data. We free it here to avoid 1282 users reusing the matrix object with different data to incur in obscure segmentation faults 1283 due to different matrix sizes */ 1284 ierr = PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL);CHKERRQ(ierr); 1285 1286 ierr = PetscObjectChangeTypeName((PetscObject)A,NULL);CHKERRQ(ierr); 1287 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr); 1288 ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr); 1289 ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr); 1290 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr); 1291 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr); 1292 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr); 1293 #if defined(PETSC_HAVE_CUDA) 1294 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr); 1295 ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL);CHKERRQ(ierr); 1296 ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr); 1297 #endif 1298 #if defined(PETSC_HAVE_KOKKOS_KERNELS) 1299 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijkokkos_C",NULL);CHKERRQ(ierr); 1300 #endif 1301 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL);CHKERRQ(ierr); 1302 #if defined(PETSC_HAVE_ELEMENTAL) 1303 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr); 1304 #endif 1305 #if defined(PETSC_HAVE_SCALAPACK) 1306 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL);CHKERRQ(ierr); 1307 #endif 1308 #if defined(PETSC_HAVE_HYPRE) 1309 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr); 1310 ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr); 1311 #endif 1312 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr); 1313 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr); 1314 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr); 1315 ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr); 1316 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr); 1317 ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr); 1318 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr); 1319 ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr); 1320 ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL);CHKERRQ(ierr); 1321 ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL);CHKERRQ(ierr); 1322 ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL);CHKERRQ(ierr); 1323 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJKron_C",NULL);CHKERRQ(ierr); 1324 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",NULL);CHKERRQ(ierr); 1325 ierr = PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",NULL);CHKERRQ(ierr); 1326 PetscFunctionReturn(0); 1327 } 1328 1329 PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg) 1330 { 1331 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1332 PetscErrorCode ierr; 1333 1334 PetscFunctionBegin; 1335 switch (op) { 1336 case MAT_ROW_ORIENTED: 1337 a->roworiented = flg; 1338 break; 1339 case MAT_KEEP_NONZERO_PATTERN: 1340 a->keepnonzeropattern = flg; 1341 break; 1342 case MAT_NEW_NONZERO_LOCATIONS: 1343 a->nonew = (flg ? 0 : 1); 1344 break; 1345 case MAT_NEW_NONZERO_LOCATION_ERR: 1346 a->nonew = (flg ? -1 : 0); 1347 break; 1348 case MAT_NEW_NONZERO_ALLOCATION_ERR: 1349 a->nonew = (flg ? -2 : 0); 1350 break; 1351 case MAT_UNUSED_NONZERO_LOCATION_ERR: 1352 a->nounused = (flg ? -1 : 0); 1353 break; 1354 case MAT_IGNORE_ZERO_ENTRIES: 1355 a->ignorezeroentries = flg; 1356 break; 1357 case MAT_SPD: 1358 case MAT_SYMMETRIC: 1359 case MAT_STRUCTURALLY_SYMMETRIC: 1360 case MAT_HERMITIAN: 1361 case MAT_SYMMETRY_ETERNAL: 1362 case MAT_STRUCTURE_ONLY: 1363 /* These options are handled directly by MatSetOption() */ 1364 break; 1365 case MAT_FORCE_DIAGONAL_ENTRIES: 1366 case MAT_IGNORE_OFF_PROC_ENTRIES: 1367 case MAT_USE_HASH_TABLE: 1368 ierr = PetscInfo(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr); 1369 break; 1370 case MAT_USE_INODES: 1371 ierr = MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg);CHKERRQ(ierr); 1372 break; 1373 case MAT_SUBMAT_SINGLEIS: 1374 A->submat_singleis = flg; 1375 break; 1376 case MAT_SORTED_FULL: 1377 if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 1378 else A->ops->setvalues = MatSetValues_SeqAIJ; 1379 break; 1380 case MAT_FORM_EXPLICIT_TRANSPOSE: 1381 A->form_explicit_transpose = flg; 1382 break; 1383 default: 1384 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op); 1385 } 1386 PetscFunctionReturn(0); 1387 } 1388 1389 PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v) 1390 { 1391 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1392 PetscErrorCode ierr; 1393 PetscInt i,j,n,*ai=a->i,*aj=a->j; 1394 PetscScalar *x; 1395 const PetscScalar *aa; 1396 1397 PetscFunctionBegin; 1398 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 1399 PetscCheckFalse(n != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 1400 ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr); 1401 if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) { 1402 PetscInt *diag=a->diag; 1403 ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr); 1404 for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]]; 1405 ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr); 1406 ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr); 1407 PetscFunctionReturn(0); 1408 } 1409 1410 ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr); 1411 for (i=0; i<n; i++) { 1412 x[i] = 0.0; 1413 for (j=ai[i]; j<ai[i+1]; j++) { 1414 if (aj[j] == i) { 1415 x[i] = aa[j]; 1416 break; 1417 } 1418 } 1419 } 1420 ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr); 1421 ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr); 1422 PetscFunctionReturn(0); 1423 } 1424 1425 #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 1426 PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy) 1427 { 1428 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1429 const MatScalar *aa; 1430 PetscScalar *y; 1431 const PetscScalar *x; 1432 PetscErrorCode ierr; 1433 PetscInt m = A->rmap->n; 1434 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 1435 const MatScalar *v; 1436 PetscScalar alpha; 1437 PetscInt n,i,j; 1438 const PetscInt *idx,*ii,*ridx=NULL; 1439 Mat_CompressedRow cprow = a->compressedrow; 1440 PetscBool usecprow = cprow.use; 1441 #endif 1442 1443 PetscFunctionBegin; 1444 if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);} 1445 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 1446 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 1447 ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr); 1448 1449 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 1450 fortranmulttransposeaddaij_(&m,x,a->i,a->j,aa,y); 1451 #else 1452 if (usecprow) { 1453 m = cprow.nrows; 1454 ii = cprow.i; 1455 ridx = cprow.rindex; 1456 } else { 1457 ii = a->i; 1458 } 1459 for (i=0; i<m; i++) { 1460 idx = a->j + ii[i]; 1461 v = aa + ii[i]; 1462 n = ii[i+1] - ii[i]; 1463 if (usecprow) { 1464 alpha = x[ridx[i]]; 1465 } else { 1466 alpha = x[i]; 1467 } 1468 for (j=0; j<n; j++) y[idx[j]] += alpha*v[j]; 1469 } 1470 #endif 1471 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1472 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1473 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 1474 ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr); 1475 PetscFunctionReturn(0); 1476 } 1477 1478 PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy) 1479 { 1480 PetscErrorCode ierr; 1481 1482 PetscFunctionBegin; 1483 ierr = VecSet(yy,0.0);CHKERRQ(ierr); 1484 ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr); 1485 PetscFunctionReturn(0); 1486 } 1487 1488 #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 1489 1490 PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy) 1491 { 1492 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1493 PetscScalar *y; 1494 const PetscScalar *x; 1495 const MatScalar *aa,*a_a; 1496 PetscErrorCode ierr; 1497 PetscInt m=A->rmap->n; 1498 const PetscInt *aj,*ii,*ridx=NULL; 1499 PetscInt n,i; 1500 PetscScalar sum; 1501 PetscBool usecprow=a->compressedrow.use; 1502 1503 #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 1504 #pragma disjoint(*x,*y,*aa) 1505 #endif 1506 1507 PetscFunctionBegin; 1508 if (a->inode.use && a->inode.checked) { 1509 ierr = MatMult_SeqAIJ_Inode(A,xx,yy);CHKERRQ(ierr); 1510 PetscFunctionReturn(0); 1511 } 1512 ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr); 1513 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 1514 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 1515 ii = a->i; 1516 if (usecprow) { /* use compressed row format */ 1517 ierr = PetscArrayzero(y,m);CHKERRQ(ierr); 1518 m = a->compressedrow.nrows; 1519 ii = a->compressedrow.i; 1520 ridx = a->compressedrow.rindex; 1521 for (i=0; i<m; i++) { 1522 n = ii[i+1] - ii[i]; 1523 aj = a->j + ii[i]; 1524 aa = a_a + ii[i]; 1525 sum = 0.0; 1526 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1527 /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 1528 y[*ridx++] = sum; 1529 } 1530 } else { /* do not use compressed row format */ 1531 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ) 1532 aj = a->j; 1533 aa = a_a; 1534 fortranmultaij_(&m,x,ii,aj,aa,y); 1535 #else 1536 for (i=0; i<m; i++) { 1537 n = ii[i+1] - ii[i]; 1538 aj = a->j + ii[i]; 1539 aa = a_a + ii[i]; 1540 sum = 0.0; 1541 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1542 y[i] = sum; 1543 } 1544 #endif 1545 } 1546 ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr); 1547 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1548 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 1549 ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr); 1550 PetscFunctionReturn(0); 1551 } 1552 1553 PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy) 1554 { 1555 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1556 PetscScalar *y; 1557 const PetscScalar *x; 1558 const MatScalar *aa,*a_a; 1559 PetscErrorCode ierr; 1560 PetscInt m=A->rmap->n; 1561 const PetscInt *aj,*ii,*ridx=NULL; 1562 PetscInt n,i,nonzerorow=0; 1563 PetscScalar sum; 1564 PetscBool usecprow=a->compressedrow.use; 1565 1566 #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 1567 #pragma disjoint(*x,*y,*aa) 1568 #endif 1569 1570 PetscFunctionBegin; 1571 ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr); 1572 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 1573 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 1574 if (usecprow) { /* use compressed row format */ 1575 m = a->compressedrow.nrows; 1576 ii = a->compressedrow.i; 1577 ridx = a->compressedrow.rindex; 1578 for (i=0; i<m; i++) { 1579 n = ii[i+1] - ii[i]; 1580 aj = a->j + ii[i]; 1581 aa = a_a + ii[i]; 1582 sum = 0.0; 1583 nonzerorow += (n>0); 1584 PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1585 /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 1586 y[*ridx++] = sum; 1587 } 1588 } else { /* do not use compressed row format */ 1589 ii = a->i; 1590 for (i=0; i<m; i++) { 1591 n = ii[i+1] - ii[i]; 1592 aj = a->j + ii[i]; 1593 aa = a_a + ii[i]; 1594 sum = 0.0; 1595 nonzerorow += (n>0); 1596 PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1597 y[i] = sum; 1598 } 1599 } 1600 ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr); 1601 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1602 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 1603 ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr); 1604 PetscFunctionReturn(0); 1605 } 1606 1607 PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1608 { 1609 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1610 PetscScalar *y,*z; 1611 const PetscScalar *x; 1612 const MatScalar *aa,*a_a; 1613 PetscErrorCode ierr; 1614 PetscInt m = A->rmap->n,*aj,*ii; 1615 PetscInt n,i,*ridx=NULL; 1616 PetscScalar sum; 1617 PetscBool usecprow=a->compressedrow.use; 1618 1619 PetscFunctionBegin; 1620 ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr); 1621 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 1622 ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr); 1623 if (usecprow) { /* use compressed row format */ 1624 if (zz != yy) { 1625 ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr); 1626 } 1627 m = a->compressedrow.nrows; 1628 ii = a->compressedrow.i; 1629 ridx = a->compressedrow.rindex; 1630 for (i=0; i<m; i++) { 1631 n = ii[i+1] - ii[i]; 1632 aj = a->j + ii[i]; 1633 aa = a_a + ii[i]; 1634 sum = y[*ridx]; 1635 PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1636 z[*ridx++] = sum; 1637 } 1638 } else { /* do not use compressed row format */ 1639 ii = a->i; 1640 for (i=0; i<m; i++) { 1641 n = ii[i+1] - ii[i]; 1642 aj = a->j + ii[i]; 1643 aa = a_a + ii[i]; 1644 sum = y[i]; 1645 PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1646 z[i] = sum; 1647 } 1648 } 1649 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1650 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1651 ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr); 1652 ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr); 1653 PetscFunctionReturn(0); 1654 } 1655 1656 #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h> 1657 PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1658 { 1659 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1660 PetscScalar *y,*z; 1661 const PetscScalar *x; 1662 const MatScalar *aa,*a_a; 1663 PetscErrorCode ierr; 1664 const PetscInt *aj,*ii,*ridx=NULL; 1665 PetscInt m = A->rmap->n,n,i; 1666 PetscScalar sum; 1667 PetscBool usecprow=a->compressedrow.use; 1668 1669 PetscFunctionBegin; 1670 if (a->inode.use && a->inode.checked) { 1671 ierr = MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz);CHKERRQ(ierr); 1672 PetscFunctionReturn(0); 1673 } 1674 ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr); 1675 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 1676 ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr); 1677 if (usecprow) { /* use compressed row format */ 1678 if (zz != yy) { 1679 ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr); 1680 } 1681 m = a->compressedrow.nrows; 1682 ii = a->compressedrow.i; 1683 ridx = a->compressedrow.rindex; 1684 for (i=0; i<m; i++) { 1685 n = ii[i+1] - ii[i]; 1686 aj = a->j + ii[i]; 1687 aa = a_a + ii[i]; 1688 sum = y[*ridx]; 1689 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1690 z[*ridx++] = sum; 1691 } 1692 } else { /* do not use compressed row format */ 1693 ii = a->i; 1694 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ) 1695 aj = a->j; 1696 aa = a_a; 1697 fortranmultaddaij_(&m,x,ii,aj,aa,y,z); 1698 #else 1699 for (i=0; i<m; i++) { 1700 n = ii[i+1] - ii[i]; 1701 aj = a->j + ii[i]; 1702 aa = a_a + ii[i]; 1703 sum = y[i]; 1704 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1705 z[i] = sum; 1706 } 1707 #endif 1708 } 1709 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1710 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1711 ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr); 1712 ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr); 1713 PetscFunctionReturn(0); 1714 } 1715 1716 /* 1717 Adds diagonal pointers to sparse matrix structure. 1718 */ 1719 PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A) 1720 { 1721 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1722 PetscErrorCode ierr; 1723 PetscInt i,j,m = A->rmap->n; 1724 1725 PetscFunctionBegin; 1726 if (!a->diag) { 1727 ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr); 1728 ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr); 1729 } 1730 for (i=0; i<A->rmap->n; i++) { 1731 a->diag[i] = a->i[i+1]; 1732 for (j=a->i[i]; j<a->i[i+1]; j++) { 1733 if (a->j[j] == i) { 1734 a->diag[i] = j; 1735 break; 1736 } 1737 } 1738 } 1739 PetscFunctionReturn(0); 1740 } 1741 1742 PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v) 1743 { 1744 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1745 const PetscInt *diag = (const PetscInt*)a->diag; 1746 const PetscInt *ii = (const PetscInt*) a->i; 1747 PetscInt i,*mdiag = NULL; 1748 PetscErrorCode ierr; 1749 PetscInt cnt = 0; /* how many diagonals are missing */ 1750 1751 PetscFunctionBegin; 1752 if (!A->preallocated || !a->nz) { 1753 ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr); 1754 ierr = MatShift_Basic(A,v);CHKERRQ(ierr); 1755 PetscFunctionReturn(0); 1756 } 1757 1758 if (a->diagonaldense) { 1759 cnt = 0; 1760 } else { 1761 ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr); 1762 for (i=0; i<A->rmap->n; i++) { 1763 if (diag[i] >= ii[i+1]) { 1764 cnt++; 1765 mdiag[i] = 1; 1766 } 1767 } 1768 } 1769 if (!cnt) { 1770 ierr = MatShift_Basic(A,v);CHKERRQ(ierr); 1771 } else { 1772 PetscScalar *olda = a->a; /* preserve pointers to current matrix nonzeros structure and values */ 1773 PetscInt *oldj = a->j, *oldi = a->i; 1774 PetscBool singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij; 1775 1776 a->a = NULL; 1777 a->j = NULL; 1778 a->i = NULL; 1779 /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */ 1780 for (i=0; i<A->rmap->n; i++) { 1781 a->imax[i] += mdiag[i]; 1782 a->imax[i] = PetscMin(a->imax[i],A->cmap->n); 1783 } 1784 ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr); 1785 1786 /* copy old values into new matrix data structure */ 1787 for (i=0; i<A->rmap->n; i++) { 1788 ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr); 1789 if (i < A->cmap->n) { 1790 ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr); 1791 } 1792 } 1793 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1794 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1795 if (singlemalloc) { 1796 ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr); 1797 } else { 1798 if (free_a) {ierr = PetscFree(olda);CHKERRQ(ierr);} 1799 if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);} 1800 if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);} 1801 } 1802 } 1803 ierr = PetscFree(mdiag);CHKERRQ(ierr); 1804 a->diagonaldense = PETSC_TRUE; 1805 PetscFunctionReturn(0); 1806 } 1807 1808 /* 1809 Checks for missing diagonals 1810 */ 1811 PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool *missing,PetscInt *d) 1812 { 1813 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1814 PetscInt *diag,*ii = a->i,i; 1815 PetscErrorCode ierr; 1816 1817 PetscFunctionBegin; 1818 *missing = PETSC_FALSE; 1819 if (A->rmap->n > 0 && !ii) { 1820 *missing = PETSC_TRUE; 1821 if (d) *d = 0; 1822 ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr); 1823 } else { 1824 PetscInt n; 1825 n = PetscMin(A->rmap->n, A->cmap->n); 1826 diag = a->diag; 1827 for (i=0; i<n; i++) { 1828 if (diag[i] >= ii[i+1]) { 1829 *missing = PETSC_TRUE; 1830 if (d) *d = i; 1831 ierr = PetscInfo(A,"Matrix is missing diagonal number %" PetscInt_FMT "\n",i);CHKERRQ(ierr); 1832 break; 1833 } 1834 } 1835 } 1836 PetscFunctionReturn(0); 1837 } 1838 1839 #include <petscblaslapack.h> 1840 #include <petsc/private/kernels/blockinvert.h> 1841 1842 /* 1843 Note that values is allocated externally by the PC and then passed into this routine 1844 */ 1845 PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag) 1846 { 1847 PetscErrorCode ierr; 1848 PetscInt n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots; 1849 PetscBool allowzeropivot,zeropivotdetected=PETSC_FALSE; 1850 const PetscReal shift = 0.0; 1851 PetscInt ipvt[5]; 1852 PetscScalar work[25],*v_work; 1853 1854 PetscFunctionBegin; 1855 allowzeropivot = PetscNot(A->erroriffailure); 1856 for (i=0; i<nblocks; i++) ncnt += bsizes[i]; 1857 PetscCheckFalse(ncnt != n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %" PetscInt_FMT " doesn't match number matrix rows %" PetscInt_FMT,ncnt,n); 1858 for (i=0; i<nblocks; i++) { 1859 bsizemax = PetscMax(bsizemax,bsizes[i]); 1860 } 1861 ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr); 1862 if (bsizemax > 7) { 1863 ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr); 1864 } 1865 ncnt = 0; 1866 for (i=0; i<nblocks; i++) { 1867 for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j; 1868 ierr = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr); 1869 switch (bsizes[i]) { 1870 case 1: 1871 *diag = 1.0/(*diag); 1872 break; 1873 case 2: 1874 ierr = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 1875 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1876 ierr = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr); 1877 break; 1878 case 3: 1879 ierr = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 1880 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1881 ierr = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr); 1882 break; 1883 case 4: 1884 ierr = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 1885 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1886 ierr = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr); 1887 break; 1888 case 5: 1889 ierr = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 1890 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1891 ierr = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr); 1892 break; 1893 case 6: 1894 ierr = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 1895 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1896 ierr = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr); 1897 break; 1898 case 7: 1899 ierr = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 1900 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1901 ierr = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr); 1902 break; 1903 default: 1904 ierr = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 1905 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1906 ierr = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr); 1907 } 1908 ncnt += bsizes[i]; 1909 diag += bsizes[i]*bsizes[i]; 1910 } 1911 if (bsizemax > 7) { 1912 ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr); 1913 } 1914 ierr = PetscFree(indx);CHKERRQ(ierr); 1915 PetscFunctionReturn(0); 1916 } 1917 1918 /* 1919 Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways 1920 */ 1921 PetscErrorCode MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift) 1922 { 1923 Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 1924 PetscErrorCode ierr; 1925 PetscInt i,*diag,m = A->rmap->n; 1926 const MatScalar *v; 1927 PetscScalar *idiag,*mdiag; 1928 1929 PetscFunctionBegin; 1930 if (a->idiagvalid) PetscFunctionReturn(0); 1931 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 1932 diag = a->diag; 1933 if (!a->idiag) { 1934 ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr); 1935 ierr = PetscLogObjectMemory((PetscObject)A,3*m*sizeof(PetscScalar));CHKERRQ(ierr); 1936 } 1937 1938 mdiag = a->mdiag; 1939 idiag = a->idiag; 1940 ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr); 1941 if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) { 1942 for (i=0; i<m; i++) { 1943 mdiag[i] = v[diag[i]]; 1944 if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */ 1945 if (PetscRealPart(fshift)) { 1946 ierr = PetscInfo(A,"Zero diagonal on row %" PetscInt_FMT "\n",i);CHKERRQ(ierr); 1947 A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 1948 A->factorerror_zeropivot_value = 0.0; 1949 A->factorerror_zeropivot_row = i; 1950 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %" PetscInt_FMT,i); 1951 } 1952 idiag[i] = 1.0/v[diag[i]]; 1953 } 1954 ierr = PetscLogFlops(m);CHKERRQ(ierr); 1955 } else { 1956 for (i=0; i<m; i++) { 1957 mdiag[i] = v[diag[i]]; 1958 idiag[i] = omega/(fshift + v[diag[i]]); 1959 } 1960 ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr); 1961 } 1962 a->idiagvalid = PETSC_TRUE; 1963 ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr); 1964 PetscFunctionReturn(0); 1965 } 1966 1967 #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h> 1968 PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 1969 { 1970 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1971 PetscScalar *x,d,sum,*t,scale; 1972 const MatScalar *v,*idiag=NULL,*mdiag,*aa; 1973 const PetscScalar *b, *bs,*xb, *ts; 1974 PetscErrorCode ierr; 1975 PetscInt n,m = A->rmap->n,i; 1976 const PetscInt *idx,*diag; 1977 1978 PetscFunctionBegin; 1979 if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) { 1980 ierr = MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx);CHKERRQ(ierr); 1981 PetscFunctionReturn(0); 1982 } 1983 its = its*lits; 1984 1985 if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */ 1986 if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);} 1987 a->fshift = fshift; 1988 a->omega = omega; 1989 1990 diag = a->diag; 1991 t = a->ssor_work; 1992 idiag = a->idiag; 1993 mdiag = a->mdiag; 1994 1995 ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr); 1996 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 1997 ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr); 1998 /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */ 1999 if (flag == SOR_APPLY_UPPER) { 2000 /* apply (U + D/omega) to the vector */ 2001 bs = b; 2002 for (i=0; i<m; i++) { 2003 d = fshift + mdiag[i]; 2004 n = a->i[i+1] - diag[i] - 1; 2005 idx = a->j + diag[i] + 1; 2006 v = aa + diag[i] + 1; 2007 sum = b[i]*d/omega; 2008 PetscSparseDensePlusDot(sum,bs,v,idx,n); 2009 x[i] = sum; 2010 } 2011 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 2012 ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr); 2013 ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr); 2014 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 2015 PetscFunctionReturn(0); 2016 } 2017 2018 PetscCheckFalse(flag == SOR_APPLY_LOWER,PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented"); 2019 else if (flag & SOR_EISENSTAT) { 2020 /* Let A = L + U + D; where L is lower triangular, 2021 U is upper triangular, E = D/omega; This routine applies 2022 2023 (L + E)^{-1} A (U + E)^{-1} 2024 2025 to a vector efficiently using Eisenstat's trick. 2026 */ 2027 scale = (2.0/omega) - 1.0; 2028 2029 /* x = (E + U)^{-1} b */ 2030 for (i=m-1; i>=0; i--) { 2031 n = a->i[i+1] - diag[i] - 1; 2032 idx = a->j + diag[i] + 1; 2033 v = aa + diag[i] + 1; 2034 sum = b[i]; 2035 PetscSparseDenseMinusDot(sum,x,v,idx,n); 2036 x[i] = sum*idiag[i]; 2037 } 2038 2039 /* t = b - (2*E - D)x */ 2040 v = aa; 2041 for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i]; 2042 2043 /* t = (E + L)^{-1}t */ 2044 ts = t; 2045 diag = a->diag; 2046 for (i=0; i<m; i++) { 2047 n = diag[i] - a->i[i]; 2048 idx = a->j + a->i[i]; 2049 v = aa + a->i[i]; 2050 sum = t[i]; 2051 PetscSparseDenseMinusDot(sum,ts,v,idx,n); 2052 t[i] = sum*idiag[i]; 2053 /* x = x + t */ 2054 x[i] += t[i]; 2055 } 2056 2057 ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr); 2058 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 2059 ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr); 2060 PetscFunctionReturn(0); 2061 } 2062 if (flag & SOR_ZERO_INITIAL_GUESS) { 2063 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 2064 for (i=0; i<m; i++) { 2065 n = diag[i] - a->i[i]; 2066 idx = a->j + a->i[i]; 2067 v = aa + a->i[i]; 2068 sum = b[i]; 2069 PetscSparseDenseMinusDot(sum,x,v,idx,n); 2070 t[i] = sum; 2071 x[i] = sum*idiag[i]; 2072 } 2073 xb = t; 2074 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 2075 } else xb = b; 2076 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 2077 for (i=m-1; i>=0; i--) { 2078 n = a->i[i+1] - diag[i] - 1; 2079 idx = a->j + diag[i] + 1; 2080 v = aa + diag[i] + 1; 2081 sum = xb[i]; 2082 PetscSparseDenseMinusDot(sum,x,v,idx,n); 2083 if (xb == b) { 2084 x[i] = sum*idiag[i]; 2085 } else { 2086 x[i] = (1-omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 2087 } 2088 } 2089 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */ 2090 } 2091 its--; 2092 } 2093 while (its--) { 2094 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 2095 for (i=0; i<m; i++) { 2096 /* lower */ 2097 n = diag[i] - a->i[i]; 2098 idx = a->j + a->i[i]; 2099 v = aa + a->i[i]; 2100 sum = b[i]; 2101 PetscSparseDenseMinusDot(sum,x,v,idx,n); 2102 t[i] = sum; /* save application of the lower-triangular part */ 2103 /* upper */ 2104 n = a->i[i+1] - diag[i] - 1; 2105 idx = a->j + diag[i] + 1; 2106 v = aa + diag[i] + 1; 2107 PetscSparseDenseMinusDot(sum,x,v,idx,n); 2108 x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 2109 } 2110 xb = t; 2111 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 2112 } else xb = b; 2113 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 2114 for (i=m-1; i>=0; i--) { 2115 sum = xb[i]; 2116 if (xb == b) { 2117 /* whole matrix (no checkpointing available) */ 2118 n = a->i[i+1] - a->i[i]; 2119 idx = a->j + a->i[i]; 2120 v = aa + a->i[i]; 2121 PetscSparseDenseMinusDot(sum,x,v,idx,n); 2122 x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i]; 2123 } else { /* lower-triangular part has been saved, so only apply upper-triangular */ 2124 n = a->i[i+1] - diag[i] - 1; 2125 idx = a->j + diag[i] + 1; 2126 v = aa + diag[i] + 1; 2127 PetscSparseDenseMinusDot(sum,x,v,idx,n); 2128 x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 2129 } 2130 } 2131 if (xb == b) { 2132 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 2133 } else { 2134 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */ 2135 } 2136 } 2137 } 2138 ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr); 2139 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 2140 ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr); 2141 PetscFunctionReturn(0); 2142 } 2143 2144 PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info) 2145 { 2146 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2147 2148 PetscFunctionBegin; 2149 info->block_size = 1.0; 2150 info->nz_allocated = a->maxnz; 2151 info->nz_used = a->nz; 2152 info->nz_unneeded = (a->maxnz - a->nz); 2153 info->assemblies = A->num_ass; 2154 info->mallocs = A->info.mallocs; 2155 info->memory = ((PetscObject)A)->mem; 2156 if (A->factortype) { 2157 info->fill_ratio_given = A->info.fill_ratio_given; 2158 info->fill_ratio_needed = A->info.fill_ratio_needed; 2159 info->factor_mallocs = A->info.factor_mallocs; 2160 } else { 2161 info->fill_ratio_given = 0; 2162 info->fill_ratio_needed = 0; 2163 info->factor_mallocs = 0; 2164 } 2165 PetscFunctionReturn(0); 2166 } 2167 2168 PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 2169 { 2170 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2171 PetscInt i,m = A->rmap->n - 1; 2172 PetscErrorCode ierr; 2173 const PetscScalar *xx; 2174 PetscScalar *bb,*aa; 2175 PetscInt d = 0; 2176 2177 PetscFunctionBegin; 2178 if (x && b) { 2179 ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 2180 ierr = VecGetArray(b,&bb);CHKERRQ(ierr); 2181 for (i=0; i<N; i++) { 2182 PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 2183 if (rows[i] >= A->cmap->n) continue; 2184 bb[rows[i]] = diag*xx[rows[i]]; 2185 } 2186 ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 2187 ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr); 2188 } 2189 2190 ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr); 2191 if (a->keepnonzeropattern) { 2192 for (i=0; i<N; i++) { 2193 PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 2194 ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr); 2195 } 2196 if (diag != 0.0) { 2197 for (i=0; i<N; i++) { 2198 d = rows[i]; 2199 if (rows[i] >= A->cmap->n) continue; 2200 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); 2201 } 2202 for (i=0; i<N; i++) { 2203 if (rows[i] >= A->cmap->n) continue; 2204 aa[a->diag[rows[i]]] = diag; 2205 } 2206 } 2207 } else { 2208 if (diag != 0.0) { 2209 for (i=0; i<N; i++) { 2210 PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 2211 if (a->ilen[rows[i]] > 0) { 2212 if (rows[i] >= A->cmap->n) { 2213 a->ilen[rows[i]] = 0; 2214 } else { 2215 a->ilen[rows[i]] = 1; 2216 aa[a->i[rows[i]]] = diag; 2217 a->j[a->i[rows[i]]] = rows[i]; 2218 } 2219 } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */ 2220 ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr); 2221 } 2222 } 2223 } else { 2224 for (i=0; i<N; i++) { 2225 PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 2226 a->ilen[rows[i]] = 0; 2227 } 2228 } 2229 A->nonzerostate++; 2230 } 2231 ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr); 2232 ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2233 PetscFunctionReturn(0); 2234 } 2235 2236 PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 2237 { 2238 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2239 PetscInt i,j,m = A->rmap->n - 1,d = 0; 2240 PetscErrorCode ierr; 2241 PetscBool missing,*zeroed,vecs = PETSC_FALSE; 2242 const PetscScalar *xx; 2243 PetscScalar *bb,*aa; 2244 2245 PetscFunctionBegin; 2246 if (!N) PetscFunctionReturn(0); 2247 ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr); 2248 if (x && b) { 2249 ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 2250 ierr = VecGetArray(b,&bb);CHKERRQ(ierr); 2251 vecs = PETSC_TRUE; 2252 } 2253 ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr); 2254 for (i=0; i<N; i++) { 2255 PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 2256 ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr); 2257 2258 zeroed[rows[i]] = PETSC_TRUE; 2259 } 2260 for (i=0; i<A->rmap->n; i++) { 2261 if (!zeroed[i]) { 2262 for (j=a->i[i]; j<a->i[i+1]; j++) { 2263 if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) { 2264 if (vecs) bb[i] -= aa[j]*xx[a->j[j]]; 2265 aa[j] = 0.0; 2266 } 2267 } 2268 } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i]; 2269 } 2270 if (x && b) { 2271 ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 2272 ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr); 2273 } 2274 ierr = PetscFree(zeroed);CHKERRQ(ierr); 2275 if (diag != 0.0) { 2276 ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr); 2277 if (missing) { 2278 for (i=0; i<N; i++) { 2279 if (rows[i] >= A->cmap->N) continue; 2280 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]); 2281 ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr); 2282 } 2283 } else { 2284 for (i=0; i<N; i++) { 2285 aa[a->diag[rows[i]]] = diag; 2286 } 2287 } 2288 } 2289 ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr); 2290 ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2291 PetscFunctionReturn(0); 2292 } 2293 2294 PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 2295 { 2296 PetscErrorCode ierr; 2297 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2298 const PetscScalar *aa; 2299 PetscInt *itmp; 2300 2301 PetscFunctionBegin; 2302 ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr); 2303 *nz = a->i[row+1] - a->i[row]; 2304 if (v) *v = (PetscScalar*)(aa + a->i[row]); 2305 if (idx) { 2306 itmp = a->j + a->i[row]; 2307 if (*nz) *idx = itmp; 2308 else *idx = NULL; 2309 } 2310 ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr); 2311 PetscFunctionReturn(0); 2312 } 2313 2314 PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 2315 { 2316 PetscFunctionBegin; 2317 if (nz) *nz = 0; 2318 if (idx) *idx = NULL; 2319 if (v) *v = NULL; 2320 PetscFunctionReturn(0); 2321 } 2322 2323 PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm) 2324 { 2325 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2326 const MatScalar *v; 2327 PetscReal sum = 0.0; 2328 PetscErrorCode ierr; 2329 PetscInt i,j; 2330 2331 PetscFunctionBegin; 2332 ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr); 2333 if (type == NORM_FROBENIUS) { 2334 #if defined(PETSC_USE_REAL___FP16) 2335 PetscBLASInt one = 1,nz = a->nz; 2336 PetscStackCallBLAS("BLASnrm2",*nrm = BLASnrm2_(&nz,v,&one)); 2337 #else 2338 for (i=0; i<a->nz; i++) { 2339 sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 2340 } 2341 *nrm = PetscSqrtReal(sum); 2342 #endif 2343 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 2344 } else if (type == NORM_1) { 2345 PetscReal *tmp; 2346 PetscInt *jj = a->j; 2347 ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr); 2348 *nrm = 0.0; 2349 for (j=0; j<a->nz; j++) { 2350 tmp[*jj++] += PetscAbsScalar(*v); v++; 2351 } 2352 for (j=0; j<A->cmap->n; j++) { 2353 if (tmp[j] > *nrm) *nrm = tmp[j]; 2354 } 2355 ierr = PetscFree(tmp);CHKERRQ(ierr); 2356 ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr); 2357 } else if (type == NORM_INFINITY) { 2358 *nrm = 0.0; 2359 for (j=0; j<A->rmap->n; j++) { 2360 const PetscScalar *v2 = v + a->i[j]; 2361 sum = 0.0; 2362 for (i=0; i<a->i[j+1]-a->i[j]; i++) { 2363 sum += PetscAbsScalar(*v2); v2++; 2364 } 2365 if (sum > *nrm) *nrm = sum; 2366 } 2367 ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr); 2368 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm"); 2369 ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr); 2370 PetscFunctionReturn(0); 2371 } 2372 2373 /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */ 2374 PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B) 2375 { 2376 PetscErrorCode ierr; 2377 PetscInt i,j,anzj; 2378 Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data,*b; 2379 PetscInt an=A->cmap->N,am=A->rmap->N; 2380 PetscInt *ati,*atj,*atfill,*ai=a->i,*aj=a->j; 2381 2382 PetscFunctionBegin; 2383 /* Allocate space for symbolic transpose info and work array */ 2384 ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr); 2385 ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr); 2386 ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr); 2387 2388 /* Walk through aj and count ## of non-zeros in each row of A^T. */ 2389 /* Note: offset by 1 for fast conversion into csr format. */ 2390 for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1; 2391 /* Form ati for csr format of A^T. */ 2392 for (i=0;i<an;i++) ati[i+1] += ati[i]; 2393 2394 /* Copy ati into atfill so we have locations of the next free space in atj */ 2395 ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr); 2396 2397 /* Walk through A row-wise and mark nonzero entries of A^T. */ 2398 for (i=0;i<am;i++) { 2399 anzj = ai[i+1] - ai[i]; 2400 for (j=0;j<anzj;j++) { 2401 atj[atfill[*aj]] = i; 2402 atfill[*aj++] += 1; 2403 } 2404 } 2405 2406 /* Clean up temporary space and complete requests. */ 2407 ierr = PetscFree(atfill);CHKERRQ(ierr); 2408 ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr); 2409 ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr); 2410 ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr); 2411 2412 b = (Mat_SeqAIJ*)((*B)->data); 2413 b->free_a = PETSC_FALSE; 2414 b->free_ij = PETSC_TRUE; 2415 b->nonew = 0; 2416 PetscFunctionReturn(0); 2417 } 2418 2419 PetscErrorCode MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f) 2420 { 2421 Mat_SeqAIJ *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data; 2422 PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr; 2423 const MatScalar *va,*vb; 2424 PetscErrorCode ierr; 2425 PetscInt ma,na,mb,nb, i; 2426 2427 PetscFunctionBegin; 2428 ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr); 2429 ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr); 2430 if (ma!=nb || na!=mb) { 2431 *f = PETSC_FALSE; 2432 PetscFunctionReturn(0); 2433 } 2434 ierr = MatSeqAIJGetArrayRead(A,&va);CHKERRQ(ierr); 2435 ierr = MatSeqAIJGetArrayRead(B,&vb);CHKERRQ(ierr); 2436 aii = aij->i; bii = bij->i; 2437 adx = aij->j; bdx = bij->j; 2438 ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr); 2439 ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr); 2440 for (i=0; i<ma; i++) aptr[i] = aii[i]; 2441 for (i=0; i<mb; i++) bptr[i] = bii[i]; 2442 2443 *f = PETSC_TRUE; 2444 for (i=0; i<ma; i++) { 2445 while (aptr[i]<aii[i+1]) { 2446 PetscInt idc,idr; 2447 PetscScalar vc,vr; 2448 /* column/row index/value */ 2449 idc = adx[aptr[i]]; 2450 idr = bdx[bptr[idc]]; 2451 vc = va[aptr[i]]; 2452 vr = vb[bptr[idc]]; 2453 if (i!=idr || PetscAbsScalar(vc-vr) > tol) { 2454 *f = PETSC_FALSE; 2455 goto done; 2456 } else { 2457 aptr[i]++; 2458 if (B || i!=idc) bptr[idc]++; 2459 } 2460 } 2461 } 2462 done: 2463 ierr = PetscFree(aptr);CHKERRQ(ierr); 2464 ierr = PetscFree(bptr);CHKERRQ(ierr); 2465 ierr = MatSeqAIJRestoreArrayRead(A,&va);CHKERRQ(ierr); 2466 ierr = MatSeqAIJRestoreArrayRead(B,&vb);CHKERRQ(ierr); 2467 PetscFunctionReturn(0); 2468 } 2469 2470 PetscErrorCode MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f) 2471 { 2472 Mat_SeqAIJ *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data; 2473 PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr; 2474 MatScalar *va,*vb; 2475 PetscErrorCode ierr; 2476 PetscInt ma,na,mb,nb, i; 2477 2478 PetscFunctionBegin; 2479 ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr); 2480 ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr); 2481 if (ma!=nb || na!=mb) { 2482 *f = PETSC_FALSE; 2483 PetscFunctionReturn(0); 2484 } 2485 aii = aij->i; bii = bij->i; 2486 adx = aij->j; bdx = bij->j; 2487 va = aij->a; vb = bij->a; 2488 ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr); 2489 ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr); 2490 for (i=0; i<ma; i++) aptr[i] = aii[i]; 2491 for (i=0; i<mb; i++) bptr[i] = bii[i]; 2492 2493 *f = PETSC_TRUE; 2494 for (i=0; i<ma; i++) { 2495 while (aptr[i]<aii[i+1]) { 2496 PetscInt idc,idr; 2497 PetscScalar vc,vr; 2498 /* column/row index/value */ 2499 idc = adx[aptr[i]]; 2500 idr = bdx[bptr[idc]]; 2501 vc = va[aptr[i]]; 2502 vr = vb[bptr[idc]]; 2503 if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) { 2504 *f = PETSC_FALSE; 2505 goto done; 2506 } else { 2507 aptr[i]++; 2508 if (B || i!=idc) bptr[idc]++; 2509 } 2510 } 2511 } 2512 done: 2513 ierr = PetscFree(aptr);CHKERRQ(ierr); 2514 ierr = PetscFree(bptr);CHKERRQ(ierr); 2515 PetscFunctionReturn(0); 2516 } 2517 2518 PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool *f) 2519 { 2520 PetscErrorCode ierr; 2521 2522 PetscFunctionBegin; 2523 ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr); 2524 PetscFunctionReturn(0); 2525 } 2526 2527 PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool *f) 2528 { 2529 PetscErrorCode ierr; 2530 2531 PetscFunctionBegin; 2532 ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr); 2533 PetscFunctionReturn(0); 2534 } 2535 2536 PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr) 2537 { 2538 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2539 const PetscScalar *l,*r; 2540 PetscScalar x; 2541 MatScalar *v; 2542 PetscErrorCode ierr; 2543 PetscInt i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz; 2544 const PetscInt *jj; 2545 2546 PetscFunctionBegin; 2547 if (ll) { 2548 /* The local size is used so that VecMPI can be passed to this routine 2549 by MatDiagonalScale_MPIAIJ */ 2550 ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr); 2551 PetscCheckFalse(m != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length"); 2552 ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr); 2553 ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr); 2554 for (i=0; i<m; i++) { 2555 x = l[i]; 2556 M = a->i[i+1] - a->i[i]; 2557 for (j=0; j<M; j++) (*v++) *= x; 2558 } 2559 ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr); 2560 ierr = PetscLogFlops(nz);CHKERRQ(ierr); 2561 ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr); 2562 } 2563 if (rr) { 2564 ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr); 2565 PetscCheckFalse(n != A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length"); 2566 ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr); 2567 ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr); 2568 jj = a->j; 2569 for (i=0; i<nz; i++) (*v++) *= r[*jj++]; 2570 ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr); 2571 ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr); 2572 ierr = PetscLogFlops(nz);CHKERRQ(ierr); 2573 } 2574 ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr); 2575 PetscFunctionReturn(0); 2576 } 2577 2578 PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B) 2579 { 2580 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*c; 2581 PetscErrorCode ierr; 2582 PetscInt *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens; 2583 PetscInt row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi; 2584 const PetscInt *irow,*icol; 2585 const PetscScalar *aa; 2586 PetscInt nrows,ncols; 2587 PetscInt *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen; 2588 MatScalar *a_new,*mat_a; 2589 Mat C; 2590 PetscBool stride; 2591 2592 PetscFunctionBegin; 2593 ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr); 2594 ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr); 2595 ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr); 2596 2597 ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr); 2598 if (stride) { 2599 ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr); 2600 } else { 2601 first = 0; 2602 step = 0; 2603 } 2604 if (stride && step == 1) { 2605 /* special case of contiguous rows */ 2606 ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr); 2607 /* loop over new rows determining lens and starting points */ 2608 for (i=0; i<nrows; i++) { 2609 kstart = ai[irow[i]]; 2610 kend = kstart + ailen[irow[i]]; 2611 starts[i] = kstart; 2612 for (k=kstart; k<kend; k++) { 2613 if (aj[k] >= first) { 2614 starts[i] = k; 2615 break; 2616 } 2617 } 2618 sum = 0; 2619 while (k < kend) { 2620 if (aj[k++] >= first+ncols) break; 2621 sum++; 2622 } 2623 lens[i] = sum; 2624 } 2625 /* create submatrix */ 2626 if (scall == MAT_REUSE_MATRIX) { 2627 PetscInt n_cols,n_rows; 2628 ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr); 2629 PetscCheckFalse(n_rows != nrows || n_cols != ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size"); 2630 ierr = MatZeroEntries(*B);CHKERRQ(ierr); 2631 C = *B; 2632 } else { 2633 PetscInt rbs,cbs; 2634 ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 2635 ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 2636 ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr); 2637 ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr); 2638 ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr); 2639 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 2640 ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr); 2641 } 2642 c = (Mat_SeqAIJ*)C->data; 2643 2644 /* loop over rows inserting into submatrix */ 2645 a_new = c->a; 2646 j_new = c->j; 2647 i_new = c->i; 2648 ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr); 2649 for (i=0; i<nrows; i++) { 2650 ii = starts[i]; 2651 lensi = lens[i]; 2652 for (k=0; k<lensi; k++) { 2653 *j_new++ = aj[ii+k] - first; 2654 } 2655 ierr = PetscArraycpy(a_new,aa + starts[i],lensi);CHKERRQ(ierr); 2656 a_new += lensi; 2657 i_new[i+1] = i_new[i] + lensi; 2658 c->ilen[i] = lensi; 2659 } 2660 ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr); 2661 ierr = PetscFree2(lens,starts);CHKERRQ(ierr); 2662 } else { 2663 ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr); 2664 ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr); 2665 ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr); 2666 for (i=0; i<ncols; i++) { 2667 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); 2668 smap[icol[i]] = i+1; 2669 } 2670 2671 /* determine lens of each row */ 2672 for (i=0; i<nrows; i++) { 2673 kstart = ai[irow[i]]; 2674 kend = kstart + a->ilen[irow[i]]; 2675 lens[i] = 0; 2676 for (k=kstart; k<kend; k++) { 2677 if (smap[aj[k]]) { 2678 lens[i]++; 2679 } 2680 } 2681 } 2682 /* Create and fill new matrix */ 2683 if (scall == MAT_REUSE_MATRIX) { 2684 PetscBool equal; 2685 2686 c = (Mat_SeqAIJ*)((*B)->data); 2687 PetscCheckFalse((*B)->rmap->n != nrows || (*B)->cmap->n != ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size"); 2688 ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr); 2689 PetscCheckFalse(!equal,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros"); 2690 ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr); 2691 C = *B; 2692 } else { 2693 PetscInt rbs,cbs; 2694 ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 2695 ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 2696 ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr); 2697 ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr); 2698 ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr); 2699 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 2700 ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr); 2701 } 2702 ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr); 2703 c = (Mat_SeqAIJ*)(C->data); 2704 for (i=0; i<nrows; i++) { 2705 row = irow[i]; 2706 kstart = ai[row]; 2707 kend = kstart + a->ilen[row]; 2708 mat_i = c->i[i]; 2709 mat_j = c->j + mat_i; 2710 mat_a = c->a + mat_i; 2711 mat_ilen = c->ilen + i; 2712 for (k=kstart; k<kend; k++) { 2713 if ((tcol=smap[a->j[k]])) { 2714 *mat_j++ = tcol - 1; 2715 *mat_a++ = aa[k]; 2716 (*mat_ilen)++; 2717 2718 } 2719 } 2720 } 2721 ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr); 2722 /* Free work space */ 2723 ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr); 2724 ierr = PetscFree(smap);CHKERRQ(ierr); 2725 ierr = PetscFree(lens);CHKERRQ(ierr); 2726 /* sort */ 2727 for (i = 0; i < nrows; i++) { 2728 PetscInt ilen; 2729 2730 mat_i = c->i[i]; 2731 mat_j = c->j + mat_i; 2732 mat_a = c->a + mat_i; 2733 ilen = c->ilen[i]; 2734 ierr = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr); 2735 } 2736 } 2737 #if defined(PETSC_HAVE_DEVICE) 2738 ierr = MatBindToCPU(C,A->boundtocpu);CHKERRQ(ierr); 2739 #endif 2740 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2741 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2742 2743 ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr); 2744 *B = C; 2745 PetscFunctionReturn(0); 2746 } 2747 2748 PetscErrorCode MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat) 2749 { 2750 PetscErrorCode ierr; 2751 Mat B; 2752 2753 PetscFunctionBegin; 2754 if (scall == MAT_INITIAL_MATRIX) { 2755 ierr = MatCreate(subComm,&B);CHKERRQ(ierr); 2756 ierr = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr); 2757 ierr = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr); 2758 ierr = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr); 2759 ierr = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr); 2760 *subMat = B; 2761 } else { 2762 ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 2763 } 2764 PetscFunctionReturn(0); 2765 } 2766 2767 PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info) 2768 { 2769 Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 2770 PetscErrorCode ierr; 2771 Mat outA; 2772 PetscBool row_identity,col_identity; 2773 2774 PetscFunctionBegin; 2775 PetscCheckFalse(info->levels != 0,PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu"); 2776 2777 ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr); 2778 ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr); 2779 2780 outA = inA; 2781 outA->factortype = MAT_FACTOR_LU; 2782 ierr = PetscFree(inA->solvertype);CHKERRQ(ierr); 2783 ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr); 2784 2785 ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr); 2786 ierr = ISDestroy(&a->row);CHKERRQ(ierr); 2787 2788 a->row = row; 2789 2790 ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr); 2791 ierr = ISDestroy(&a->col);CHKERRQ(ierr); 2792 2793 a->col = col; 2794 2795 /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */ 2796 ierr = ISDestroy(&a->icol);CHKERRQ(ierr); 2797 ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr); 2798 ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr); 2799 2800 if (!a->solve_work) { /* this matrix may have been factored before */ 2801 ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr); 2802 ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr); 2803 } 2804 2805 ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr); 2806 if (row_identity && col_identity) { 2807 ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr); 2808 } else { 2809 ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr); 2810 } 2811 PetscFunctionReturn(0); 2812 } 2813 2814 PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha) 2815 { 2816 Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 2817 PetscScalar *v; 2818 PetscErrorCode ierr; 2819 PetscBLASInt one = 1,bnz; 2820 2821 PetscFunctionBegin; 2822 ierr = MatSeqAIJGetArray(inA,&v);CHKERRQ(ierr); 2823 ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr); 2824 PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&alpha,v,&one)); 2825 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 2826 ierr = MatSeqAIJRestoreArray(inA,&v);CHKERRQ(ierr); 2827 ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr); 2828 PetscFunctionReturn(0); 2829 } 2830 2831 PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj) 2832 { 2833 PetscErrorCode ierr; 2834 PetscInt i; 2835 2836 PetscFunctionBegin; 2837 if (!submatj->id) { /* delete data that are linked only to submats[id=0] */ 2838 ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr); 2839 2840 for (i=0; i<submatj->nrqr; ++i) { 2841 ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr); 2842 } 2843 ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr); 2844 2845 if (submatj->rbuf1) { 2846 ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr); 2847 ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr); 2848 } 2849 2850 for (i=0; i<submatj->nrqs; ++i) { 2851 ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr); 2852 } 2853 ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr); 2854 ierr = PetscFree(submatj->pa);CHKERRQ(ierr); 2855 } 2856 2857 #if defined(PETSC_USE_CTABLE) 2858 ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr); 2859 if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);} 2860 ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr); 2861 #else 2862 ierr = PetscFree(submatj->rmap);CHKERRQ(ierr); 2863 #endif 2864 2865 if (!submatj->allcolumns) { 2866 #if defined(PETSC_USE_CTABLE) 2867 ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr); 2868 #else 2869 ierr = PetscFree(submatj->cmap);CHKERRQ(ierr); 2870 #endif 2871 } 2872 ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr); 2873 2874 ierr = PetscFree(submatj);CHKERRQ(ierr); 2875 PetscFunctionReturn(0); 2876 } 2877 2878 PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C) 2879 { 2880 PetscErrorCode ierr; 2881 Mat_SeqAIJ *c = (Mat_SeqAIJ*)C->data; 2882 Mat_SubSppt *submatj = c->submatis1; 2883 2884 PetscFunctionBegin; 2885 ierr = (*submatj->destroy)(C);CHKERRQ(ierr); 2886 ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr); 2887 PetscFunctionReturn(0); 2888 } 2889 2890 PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[]) 2891 { 2892 PetscErrorCode ierr; 2893 PetscInt i; 2894 Mat C; 2895 Mat_SeqAIJ *c; 2896 Mat_SubSppt *submatj; 2897 2898 PetscFunctionBegin; 2899 for (i=0; i<n; i++) { 2900 C = (*mat)[i]; 2901 c = (Mat_SeqAIJ*)C->data; 2902 submatj = c->submatis1; 2903 if (submatj) { 2904 if (--((PetscObject)C)->refct <= 0) { 2905 ierr = (*submatj->destroy)(C);CHKERRQ(ierr); 2906 ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr); 2907 ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr); 2908 ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr); 2909 ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr); 2910 ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr); 2911 } 2912 } else { 2913 ierr = MatDestroy(&C);CHKERRQ(ierr); 2914 } 2915 } 2916 2917 /* Destroy Dummy submatrices created for reuse */ 2918 ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr); 2919 2920 ierr = PetscFree(*mat);CHKERRQ(ierr); 2921 PetscFunctionReturn(0); 2922 } 2923 2924 PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[]) 2925 { 2926 PetscErrorCode ierr; 2927 PetscInt i; 2928 2929 PetscFunctionBegin; 2930 if (scall == MAT_INITIAL_MATRIX) { 2931 ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr); 2932 } 2933 2934 for (i=0; i<n; i++) { 2935 ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr); 2936 } 2937 PetscFunctionReturn(0); 2938 } 2939 2940 PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov) 2941 { 2942 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2943 PetscErrorCode ierr; 2944 PetscInt row,i,j,k,l,m,n,*nidx,isz,val; 2945 const PetscInt *idx; 2946 PetscInt start,end,*ai,*aj; 2947 PetscBT table; 2948 2949 PetscFunctionBegin; 2950 m = A->rmap->n; 2951 ai = a->i; 2952 aj = a->j; 2953 2954 PetscCheckFalse(ov < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used"); 2955 2956 ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr); 2957 ierr = PetscBTCreate(m,&table);CHKERRQ(ierr); 2958 2959 for (i=0; i<is_max; i++) { 2960 /* Initialize the two local arrays */ 2961 isz = 0; 2962 ierr = PetscBTMemzero(m,table);CHKERRQ(ierr); 2963 2964 /* Extract the indices, assume there can be duplicate entries */ 2965 ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr); 2966 ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr); 2967 2968 /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 2969 for (j=0; j<n; ++j) { 2970 if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j]; 2971 } 2972 ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr); 2973 ierr = ISDestroy(&is[i]);CHKERRQ(ierr); 2974 2975 k = 0; 2976 for (j=0; j<ov; j++) { /* for each overlap */ 2977 n = isz; 2978 for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */ 2979 row = nidx[k]; 2980 start = ai[row]; 2981 end = ai[row+1]; 2982 for (l = start; l<end; l++) { 2983 val = aj[l]; 2984 if (!PetscBTLookupSet(table,val)) nidx[isz++] = val; 2985 } 2986 } 2987 } 2988 ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr); 2989 } 2990 ierr = PetscBTDestroy(&table);CHKERRQ(ierr); 2991 ierr = PetscFree(nidx);CHKERRQ(ierr); 2992 PetscFunctionReturn(0); 2993 } 2994 2995 /* -------------------------------------------------------------- */ 2996 PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B) 2997 { 2998 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2999 PetscErrorCode ierr; 3000 PetscInt i,nz = 0,m = A->rmap->n,n = A->cmap->n; 3001 const PetscInt *row,*col; 3002 PetscInt *cnew,j,*lens; 3003 IS icolp,irowp; 3004 PetscInt *cwork = NULL; 3005 PetscScalar *vwork = NULL; 3006 3007 PetscFunctionBegin; 3008 ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr); 3009 ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr); 3010 ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr); 3011 ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr); 3012 3013 /* determine lengths of permuted rows */ 3014 ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr); 3015 for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i]; 3016 ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr); 3017 ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr); 3018 ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr); 3019 ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr); 3020 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr); 3021 ierr = PetscFree(lens);CHKERRQ(ierr); 3022 3023 ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr); 3024 for (i=0; i<m; i++) { 3025 ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr); 3026 for (j=0; j<nz; j++) cnew[j] = col[cwork[j]]; 3027 ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr); 3028 ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr); 3029 } 3030 ierr = PetscFree(cnew);CHKERRQ(ierr); 3031 3032 (*B)->assembled = PETSC_FALSE; 3033 3034 #if defined(PETSC_HAVE_DEVICE) 3035 ierr = MatBindToCPU(*B,A->boundtocpu);CHKERRQ(ierr); 3036 #endif 3037 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3038 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3039 ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr); 3040 ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr); 3041 ierr = ISDestroy(&irowp);CHKERRQ(ierr); 3042 ierr = ISDestroy(&icolp);CHKERRQ(ierr); 3043 if (rowp == colp) { 3044 ierr = MatPropagateSymmetryOptions(A,*B);CHKERRQ(ierr); 3045 } 3046 PetscFunctionReturn(0); 3047 } 3048 3049 PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str) 3050 { 3051 PetscErrorCode ierr; 3052 3053 PetscFunctionBegin; 3054 /* If the two matrices have the same copy implementation, use fast copy. */ 3055 if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) { 3056 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3057 Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 3058 const PetscScalar *aa; 3059 3060 ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr); 3061 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]); 3062 ierr = PetscArraycpy(b->a,aa,a->i[A->rmap->n]);CHKERRQ(ierr); 3063 ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr); 3064 ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr); 3065 } else { 3066 ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr); 3067 } 3068 PetscFunctionReturn(0); 3069 } 3070 3071 PetscErrorCode MatSetUp_SeqAIJ(Mat A) 3072 { 3073 PetscErrorCode ierr; 3074 3075 PetscFunctionBegin; 3076 ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL);CHKERRQ(ierr); 3077 PetscFunctionReturn(0); 3078 } 3079 3080 PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[]) 3081 { 3082 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3083 3084 PetscFunctionBegin; 3085 *array = a->a; 3086 PetscFunctionReturn(0); 3087 } 3088 3089 PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[]) 3090 { 3091 PetscFunctionBegin; 3092 *array = NULL; 3093 PetscFunctionReturn(0); 3094 } 3095 3096 /* 3097 Computes the number of nonzeros per row needed for preallocation when X and Y 3098 have different nonzero structure. 3099 */ 3100 PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz) 3101 { 3102 PetscInt i,j,k,nzx,nzy; 3103 3104 PetscFunctionBegin; 3105 /* Set the number of nonzeros in the new matrix */ 3106 for (i=0; i<m; i++) { 3107 const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i]; 3108 nzx = xi[i+1] - xi[i]; 3109 nzy = yi[i+1] - yi[i]; 3110 nnz[i] = 0; 3111 for (j=0,k=0; j<nzx; j++) { /* Point in X */ 3112 for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */ 3113 if (k<nzy && yjj[k]==xjj[j]) k++; /* Skip duplicate */ 3114 nnz[i]++; 3115 } 3116 for (; k<nzy; k++) nnz[i]++; 3117 } 3118 PetscFunctionReturn(0); 3119 } 3120 3121 PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz) 3122 { 3123 PetscInt m = Y->rmap->N; 3124 Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data; 3125 Mat_SeqAIJ *y = (Mat_SeqAIJ*)Y->data; 3126 PetscErrorCode ierr; 3127 3128 PetscFunctionBegin; 3129 /* Set the number of nonzeros in the new matrix */ 3130 ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr); 3131 PetscFunctionReturn(0); 3132 } 3133 3134 PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str) 3135 { 3136 PetscErrorCode ierr; 3137 Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data; 3138 3139 PetscFunctionBegin; 3140 if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) { 3141 PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE; 3142 if (e) { 3143 ierr = PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e);CHKERRQ(ierr); 3144 if (e) { 3145 ierr = PetscArraycmp(x->j,y->j,y->nz,&e);CHKERRQ(ierr); 3146 if (e) str = SAME_NONZERO_PATTERN; 3147 } 3148 } 3149 if (!e && str == SAME_NONZERO_PATTERN) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MatStructure is not SAME_NONZERO_PATTERN"); 3150 } 3151 if (str == SAME_NONZERO_PATTERN) { 3152 const PetscScalar *xa; 3153 PetscScalar *ya,alpha = a; 3154 PetscBLASInt one = 1,bnz; 3155 3156 ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr); 3157 ierr = MatSeqAIJGetArray(Y,&ya);CHKERRQ(ierr); 3158 ierr = MatSeqAIJGetArrayRead(X,&xa);CHKERRQ(ierr); 3159 PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,xa,&one,ya,&one)); 3160 ierr = MatSeqAIJRestoreArrayRead(X,&xa);CHKERRQ(ierr); 3161 ierr = MatSeqAIJRestoreArray(Y,&ya);CHKERRQ(ierr); 3162 ierr = PetscLogFlops(2.0*bnz);CHKERRQ(ierr); 3163 ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr); 3164 ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr); 3165 } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 3166 ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr); 3167 } else { 3168 Mat B; 3169 PetscInt *nnz; 3170 ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr); 3171 ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr); 3172 ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr); 3173 ierr = MatSetLayouts(B,Y->rmap,Y->cmap);CHKERRQ(ierr); 3174 ierr = MatSetType(B,((PetscObject)Y)->type_name);CHKERRQ(ierr); 3175 ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr); 3176 ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr); 3177 ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr); 3178 ierr = MatHeaderMerge(Y,&B);CHKERRQ(ierr); 3179 ierr = PetscFree(nnz);CHKERRQ(ierr); 3180 } 3181 PetscFunctionReturn(0); 3182 } 3183 3184 PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat) 3185 { 3186 #if defined(PETSC_USE_COMPLEX) 3187 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3188 PetscInt i,nz; 3189 PetscScalar *a; 3190 PetscErrorCode ierr; 3191 3192 PetscFunctionBegin; 3193 nz = aij->nz; 3194 ierr = MatSeqAIJGetArray(mat,&a);CHKERRQ(ierr); 3195 for (i=0; i<nz; i++) a[i] = PetscConj(a[i]); 3196 ierr = MatSeqAIJRestoreArray(mat,&a);CHKERRQ(ierr); 3197 #else 3198 PetscFunctionBegin; 3199 #endif 3200 PetscFunctionReturn(0); 3201 } 3202 3203 PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3204 { 3205 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3206 PetscErrorCode ierr; 3207 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 3208 PetscReal atmp; 3209 PetscScalar *x; 3210 const MatScalar *aa,*av; 3211 3212 PetscFunctionBegin; 3213 PetscCheckFalse(A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3214 ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr); 3215 aa = av; 3216 ai = a->i; 3217 aj = a->j; 3218 3219 ierr = VecSet(v,0.0);CHKERRQ(ierr); 3220 ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr); 3221 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 3222 PetscCheckFalse(n != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 3223 for (i=0; i<m; i++) { 3224 ncols = ai[1] - ai[0]; ai++; 3225 for (j=0; j<ncols; j++) { 3226 atmp = PetscAbsScalar(*aa); 3227 if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;} 3228 aa++; aj++; 3229 } 3230 } 3231 ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr); 3232 ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr); 3233 PetscFunctionReturn(0); 3234 } 3235 3236 PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3237 { 3238 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3239 PetscErrorCode ierr; 3240 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 3241 PetscScalar *x; 3242 const MatScalar *aa,*av; 3243 3244 PetscFunctionBegin; 3245 PetscCheckFalse(A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3246 ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr); 3247 aa = av; 3248 ai = a->i; 3249 aj = a->j; 3250 3251 ierr = VecSet(v,0.0);CHKERRQ(ierr); 3252 ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr); 3253 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 3254 PetscCheckFalse(n != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 3255 for (i=0; i<m; i++) { 3256 ncols = ai[1] - ai[0]; ai++; 3257 if (ncols == A->cmap->n) { /* row is dense */ 3258 x[i] = *aa; if (idx) idx[i] = 0; 3259 } else { /* row is sparse so already KNOW maximum is 0.0 or higher */ 3260 x[i] = 0.0; 3261 if (idx) { 3262 for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */ 3263 if (aj[j] > j) { 3264 idx[i] = j; 3265 break; 3266 } 3267 } 3268 /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3269 if (j==ncols && j < A->cmap->n) idx[i] = j; 3270 } 3271 } 3272 for (j=0; j<ncols; j++) { 3273 if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 3274 aa++; aj++; 3275 } 3276 } 3277 ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr); 3278 ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr); 3279 PetscFunctionReturn(0); 3280 } 3281 3282 PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3283 { 3284 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3285 PetscErrorCode ierr; 3286 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 3287 PetscScalar *x; 3288 const MatScalar *aa,*av; 3289 3290 PetscFunctionBegin; 3291 ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr); 3292 aa = av; 3293 ai = a->i; 3294 aj = a->j; 3295 3296 ierr = VecSet(v,0.0);CHKERRQ(ierr); 3297 ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr); 3298 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 3299 PetscCheckFalse(n != m,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n); 3300 for (i=0; i<m; i++) { 3301 ncols = ai[1] - ai[0]; ai++; 3302 if (ncols == A->cmap->n) { /* row is dense */ 3303 x[i] = *aa; if (idx) idx[i] = 0; 3304 } else { /* row is sparse so already KNOW minimum is 0.0 or higher */ 3305 x[i] = 0.0; 3306 if (idx) { /* find first implicit 0.0 in the row */ 3307 for (j=0; j<ncols; j++) { 3308 if (aj[j] > j) { 3309 idx[i] = j; 3310 break; 3311 } 3312 } 3313 /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3314 if (j==ncols && j < A->cmap->n) idx[i] = j; 3315 } 3316 } 3317 for (j=0; j<ncols; j++) { 3318 if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 3319 aa++; aj++; 3320 } 3321 } 3322 ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr); 3323 ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr); 3324 PetscFunctionReturn(0); 3325 } 3326 3327 PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3328 { 3329 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3330 PetscErrorCode ierr; 3331 PetscInt i,j,m = A->rmap->n,ncols,n; 3332 const PetscInt *ai,*aj; 3333 PetscScalar *x; 3334 const MatScalar *aa,*av; 3335 3336 PetscFunctionBegin; 3337 PetscCheckFalse(A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3338 ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr); 3339 aa = av; 3340 ai = a->i; 3341 aj = a->j; 3342 3343 ierr = VecSet(v,0.0);CHKERRQ(ierr); 3344 ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr); 3345 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 3346 PetscCheckFalse(n != m,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 3347 for (i=0; i<m; i++) { 3348 ncols = ai[1] - ai[0]; ai++; 3349 if (ncols == A->cmap->n) { /* row is dense */ 3350 x[i] = *aa; if (idx) idx[i] = 0; 3351 } else { /* row is sparse so already KNOW minimum is 0.0 or lower */ 3352 x[i] = 0.0; 3353 if (idx) { /* find first implicit 0.0 in the row */ 3354 for (j=0; j<ncols; j++) { 3355 if (aj[j] > j) { 3356 idx[i] = j; 3357 break; 3358 } 3359 } 3360 /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3361 if (j==ncols && j < A->cmap->n) idx[i] = j; 3362 } 3363 } 3364 for (j=0; j<ncols; j++) { 3365 if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 3366 aa++; aj++; 3367 } 3368 } 3369 ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr); 3370 ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr); 3371 PetscFunctionReturn(0); 3372 } 3373 3374 PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values) 3375 { 3376 Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 3377 PetscErrorCode ierr; 3378 PetscInt i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j; 3379 MatScalar *diag,work[25],*v_work; 3380 const PetscReal shift = 0.0; 3381 PetscBool allowzeropivot,zeropivotdetected=PETSC_FALSE; 3382 3383 PetscFunctionBegin; 3384 allowzeropivot = PetscNot(A->erroriffailure); 3385 if (a->ibdiagvalid) { 3386 if (values) *values = a->ibdiag; 3387 PetscFunctionReturn(0); 3388 } 3389 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 3390 if (!a->ibdiag) { 3391 ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr); 3392 ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr); 3393 } 3394 diag = a->ibdiag; 3395 if (values) *values = a->ibdiag; 3396 /* factor and invert each block */ 3397 switch (bs) { 3398 case 1: 3399 for (i=0; i<mbs; i++) { 3400 ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr); 3401 if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) { 3402 if (allowzeropivot) { 3403 A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3404 A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]); 3405 A->factorerror_zeropivot_row = i; 3406 ierr = PetscInfo(A,"Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr); 3407 } 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); 3408 } 3409 diag[i] = (PetscScalar)1.0 / (diag[i] + shift); 3410 } 3411 break; 3412 case 2: 3413 for (i=0; i<mbs; i++) { 3414 ij[0] = 2*i; ij[1] = 2*i + 1; 3415 ierr = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr); 3416 ierr = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 3417 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3418 ierr = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr); 3419 diag += 4; 3420 } 3421 break; 3422 case 3: 3423 for (i=0; i<mbs; i++) { 3424 ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2; 3425 ierr = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr); 3426 ierr = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 3427 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3428 ierr = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr); 3429 diag += 9; 3430 } 3431 break; 3432 case 4: 3433 for (i=0; i<mbs; i++) { 3434 ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3; 3435 ierr = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr); 3436 ierr = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 3437 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3438 ierr = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr); 3439 diag += 16; 3440 } 3441 break; 3442 case 5: 3443 for (i=0; i<mbs; i++) { 3444 ij[0] = 5*i; ij[1] = 5*i + 1; ij[2] = 5*i + 2; ij[3] = 5*i + 3; ij[4] = 5*i + 4; 3445 ierr = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr); 3446 ierr = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 3447 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3448 ierr = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr); 3449 diag += 25; 3450 } 3451 break; 3452 case 6: 3453 for (i=0; i<mbs; i++) { 3454 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; 3455 ierr = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr); 3456 ierr = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 3457 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3458 ierr = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr); 3459 diag += 36; 3460 } 3461 break; 3462 case 7: 3463 for (i=0; i<mbs; i++) { 3464 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; 3465 ierr = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr); 3466 ierr = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 3467 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3468 ierr = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr); 3469 diag += 49; 3470 } 3471 break; 3472 default: 3473 ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr); 3474 for (i=0; i<mbs; i++) { 3475 for (j=0; j<bs; j++) { 3476 IJ[j] = bs*i + j; 3477 } 3478 ierr = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr); 3479 ierr = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr); 3480 if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 3481 ierr = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr); 3482 diag += bs2; 3483 } 3484 ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr); 3485 } 3486 a->ibdiagvalid = PETSC_TRUE; 3487 PetscFunctionReturn(0); 3488 } 3489 3490 static PetscErrorCode MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx) 3491 { 3492 PetscErrorCode ierr; 3493 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)x->data; 3494 PetscScalar a,*aa; 3495 PetscInt m,n,i,j,col; 3496 3497 PetscFunctionBegin; 3498 if (!x->assembled) { 3499 ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr); 3500 for (i=0; i<m; i++) { 3501 for (j=0; j<aij->imax[i]; j++) { 3502 ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr); 3503 col = (PetscInt)(n*PetscRealPart(a)); 3504 ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr); 3505 } 3506 } 3507 } else { 3508 ierr = MatSeqAIJGetArrayWrite(x,&aa);CHKERRQ(ierr); 3509 for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aa+i);CHKERRQ(ierr);} 3510 ierr = MatSeqAIJRestoreArrayWrite(x,&aa);CHKERRQ(ierr); 3511 } 3512 ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3513 ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3514 PetscFunctionReturn(0); 3515 } 3516 3517 /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */ 3518 PetscErrorCode MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx) 3519 { 3520 PetscErrorCode ierr; 3521 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)x->data; 3522 PetscScalar a; 3523 PetscInt m,n,i,j,col,nskip; 3524 3525 PetscFunctionBegin; 3526 nskip = high - low; 3527 ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr); 3528 n -= nskip; /* shrink number of columns where nonzeros can be set */ 3529 for (i=0; i<m; i++) { 3530 for (j=0; j<aij->imax[i]; j++) { 3531 ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr); 3532 col = (PetscInt)(n*PetscRealPart(a)); 3533 if (col >= low) col += nskip; /* shift col rightward to skip the hole */ 3534 ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr); 3535 } 3536 } 3537 ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3538 ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3539 PetscFunctionReturn(0); 3540 } 3541 3542 /* -------------------------------------------------------------------*/ 3543 static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ, 3544 MatGetRow_SeqAIJ, 3545 MatRestoreRow_SeqAIJ, 3546 MatMult_SeqAIJ, 3547 /* 4*/ MatMultAdd_SeqAIJ, 3548 MatMultTranspose_SeqAIJ, 3549 MatMultTransposeAdd_SeqAIJ, 3550 NULL, 3551 NULL, 3552 NULL, 3553 /* 10*/ NULL, 3554 MatLUFactor_SeqAIJ, 3555 NULL, 3556 MatSOR_SeqAIJ, 3557 MatTranspose_SeqAIJ, 3558 /*1 5*/ MatGetInfo_SeqAIJ, 3559 MatEqual_SeqAIJ, 3560 MatGetDiagonal_SeqAIJ, 3561 MatDiagonalScale_SeqAIJ, 3562 MatNorm_SeqAIJ, 3563 /* 20*/ NULL, 3564 MatAssemblyEnd_SeqAIJ, 3565 MatSetOption_SeqAIJ, 3566 MatZeroEntries_SeqAIJ, 3567 /* 24*/ MatZeroRows_SeqAIJ, 3568 NULL, 3569 NULL, 3570 NULL, 3571 NULL, 3572 /* 29*/ MatSetUp_SeqAIJ, 3573 NULL, 3574 NULL, 3575 NULL, 3576 NULL, 3577 /* 34*/ MatDuplicate_SeqAIJ, 3578 NULL, 3579 NULL, 3580 MatILUFactor_SeqAIJ, 3581 NULL, 3582 /* 39*/ MatAXPY_SeqAIJ, 3583 MatCreateSubMatrices_SeqAIJ, 3584 MatIncreaseOverlap_SeqAIJ, 3585 MatGetValues_SeqAIJ, 3586 MatCopy_SeqAIJ, 3587 /* 44*/ MatGetRowMax_SeqAIJ, 3588 MatScale_SeqAIJ, 3589 MatShift_SeqAIJ, 3590 MatDiagonalSet_SeqAIJ, 3591 MatZeroRowsColumns_SeqAIJ, 3592 /* 49*/ MatSetRandom_SeqAIJ, 3593 MatGetRowIJ_SeqAIJ, 3594 MatRestoreRowIJ_SeqAIJ, 3595 MatGetColumnIJ_SeqAIJ, 3596 MatRestoreColumnIJ_SeqAIJ, 3597 /* 54*/ MatFDColoringCreate_SeqXAIJ, 3598 NULL, 3599 NULL, 3600 MatPermute_SeqAIJ, 3601 NULL, 3602 /* 59*/ NULL, 3603 MatDestroy_SeqAIJ, 3604 MatView_SeqAIJ, 3605 NULL, 3606 NULL, 3607 /* 64*/ NULL, 3608 MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ, 3609 NULL, 3610 NULL, 3611 NULL, 3612 /* 69*/ MatGetRowMaxAbs_SeqAIJ, 3613 MatGetRowMinAbs_SeqAIJ, 3614 NULL, 3615 NULL, 3616 NULL, 3617 /* 74*/ NULL, 3618 MatFDColoringApply_AIJ, 3619 NULL, 3620 NULL, 3621 NULL, 3622 /* 79*/ MatFindZeroDiagonals_SeqAIJ, 3623 NULL, 3624 NULL, 3625 NULL, 3626 MatLoad_SeqAIJ, 3627 /* 84*/ MatIsSymmetric_SeqAIJ, 3628 MatIsHermitian_SeqAIJ, 3629 NULL, 3630 NULL, 3631 NULL, 3632 /* 89*/ NULL, 3633 NULL, 3634 MatMatMultNumeric_SeqAIJ_SeqAIJ, 3635 NULL, 3636 NULL, 3637 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy, 3638 NULL, 3639 NULL, 3640 MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ, 3641 NULL, 3642 /* 99*/ MatProductSetFromOptions_SeqAIJ, 3643 NULL, 3644 NULL, 3645 MatConjugate_SeqAIJ, 3646 NULL, 3647 /*104*/ MatSetValuesRow_SeqAIJ, 3648 MatRealPart_SeqAIJ, 3649 MatImaginaryPart_SeqAIJ, 3650 NULL, 3651 NULL, 3652 /*109*/ MatMatSolve_SeqAIJ, 3653 NULL, 3654 MatGetRowMin_SeqAIJ, 3655 NULL, 3656 MatMissingDiagonal_SeqAIJ, 3657 /*114*/ NULL, 3658 NULL, 3659 NULL, 3660 NULL, 3661 NULL, 3662 /*119*/ NULL, 3663 NULL, 3664 NULL, 3665 NULL, 3666 MatGetMultiProcBlock_SeqAIJ, 3667 /*124*/ MatFindNonzeroRows_SeqAIJ, 3668 MatGetColumnReductions_SeqAIJ, 3669 MatInvertBlockDiagonal_SeqAIJ, 3670 MatInvertVariableBlockDiagonal_SeqAIJ, 3671 NULL, 3672 /*129*/ NULL, 3673 NULL, 3674 NULL, 3675 MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ, 3676 MatTransposeColoringCreate_SeqAIJ, 3677 /*134*/ MatTransColoringApplySpToDen_SeqAIJ, 3678 MatTransColoringApplyDenToSp_SeqAIJ, 3679 NULL, 3680 NULL, 3681 MatRARtNumeric_SeqAIJ_SeqAIJ, 3682 /*139*/NULL, 3683 NULL, 3684 NULL, 3685 MatFDColoringSetUp_SeqXAIJ, 3686 MatFindOffBlockDiagonalEntries_SeqAIJ, 3687 MatCreateMPIMatConcatenateSeqMat_SeqAIJ, 3688 /*145*/MatDestroySubMatrices_SeqAIJ, 3689 NULL, 3690 NULL 3691 }; 3692 3693 PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices) 3694 { 3695 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3696 PetscInt i,nz,n; 3697 3698 PetscFunctionBegin; 3699 nz = aij->maxnz; 3700 n = mat->rmap->n; 3701 for (i=0; i<nz; i++) { 3702 aij->j[i] = indices[i]; 3703 } 3704 aij->nz = nz; 3705 for (i=0; i<n; i++) { 3706 aij->ilen[i] = aij->imax[i]; 3707 } 3708 PetscFunctionReturn(0); 3709 } 3710 3711 /* 3712 * Given a sparse matrix with global column indices, compact it by using a local column space. 3713 * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable() 3714 */ 3715 PetscErrorCode MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping) 3716 { 3717 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3718 PetscTable gid1_lid1; 3719 PetscTablePosition tpos; 3720 PetscInt gid,lid,i,ec,nz = aij->nz; 3721 PetscInt *garray,*jj = aij->j; 3722 PetscErrorCode ierr; 3723 3724 PetscFunctionBegin; 3725 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3726 PetscValidPointer(mapping,2); 3727 /* use a table */ 3728 ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr); 3729 ec = 0; 3730 for (i=0; i<nz; i++) { 3731 PetscInt data,gid1 = jj[i] + 1; 3732 ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr); 3733 if (!data) { 3734 /* one based table */ 3735 ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr); 3736 } 3737 } 3738 /* form array of columns we need */ 3739 ierr = PetscMalloc1(ec,&garray);CHKERRQ(ierr); 3740 ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr); 3741 while (tpos) { 3742 ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr); 3743 gid--; 3744 lid--; 3745 garray[lid] = gid; 3746 } 3747 ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */ 3748 ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr); 3749 for (i=0; i<ec; i++) { 3750 ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr); 3751 } 3752 /* compact out the extra columns in B */ 3753 for (i=0; i<nz; i++) { 3754 PetscInt gid1 = jj[i] + 1; 3755 ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr); 3756 lid--; 3757 jj[i] = lid; 3758 } 3759 ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr); 3760 ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr); 3761 ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr); 3762 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr); 3763 ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 3764 PetscFunctionReturn(0); 3765 } 3766 3767 /*@ 3768 MatSeqAIJSetColumnIndices - Set the column indices for all the rows 3769 in the matrix. 3770 3771 Input Parameters: 3772 + mat - the SeqAIJ matrix 3773 - indices - the column indices 3774 3775 Level: advanced 3776 3777 Notes: 3778 This can be called if you have precomputed the nonzero structure of the 3779 matrix and want to provide it to the matrix object to improve the performance 3780 of the MatSetValues() operation. 3781 3782 You MUST have set the correct numbers of nonzeros per row in the call to 3783 MatCreateSeqAIJ(), and the columns indices MUST be sorted. 3784 3785 MUST be called before any calls to MatSetValues(); 3786 3787 The indices should start with zero, not one. 3788 3789 @*/ 3790 PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices) 3791 { 3792 PetscErrorCode ierr; 3793 3794 PetscFunctionBegin; 3795 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3796 PetscValidPointer(indices,2); 3797 ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr); 3798 PetscFunctionReturn(0); 3799 } 3800 3801 /* ----------------------------------------------------------------------------------------*/ 3802 3803 PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) 3804 { 3805 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3806 PetscErrorCode ierr; 3807 size_t nz = aij->i[mat->rmap->n]; 3808 3809 PetscFunctionBegin; 3810 PetscCheckFalse(!aij->nonew,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3811 3812 /* allocate space for values if not already there */ 3813 if (!aij->saved_values) { 3814 ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr); 3815 ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr); 3816 } 3817 3818 /* copy values over */ 3819 ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr); 3820 PetscFunctionReturn(0); 3821 } 3822 3823 /*@ 3824 MatStoreValues - Stashes a copy of the matrix values; this allows, for 3825 example, reuse of the linear part of a Jacobian, while recomputing the 3826 nonlinear portion. 3827 3828 Collect on Mat 3829 3830 Input Parameters: 3831 . mat - the matrix (currently only AIJ matrices support this option) 3832 3833 Level: advanced 3834 3835 Common Usage, with SNESSolve(): 3836 $ Create Jacobian matrix 3837 $ Set linear terms into matrix 3838 $ Apply boundary conditions to matrix, at this time matrix must have 3839 $ final nonzero structure (i.e. setting the nonlinear terms and applying 3840 $ boundary conditions again will not change the nonzero structure 3841 $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3842 $ ierr = MatStoreValues(mat); 3843 $ Call SNESSetJacobian() with matrix 3844 $ In your Jacobian routine 3845 $ ierr = MatRetrieveValues(mat); 3846 $ Set nonlinear terms in matrix 3847 3848 Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself: 3849 $ // build linear portion of Jacobian 3850 $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3851 $ ierr = MatStoreValues(mat); 3852 $ loop over nonlinear iterations 3853 $ ierr = MatRetrieveValues(mat); 3854 $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian 3855 $ // call MatAssemblyBegin/End() on matrix 3856 $ Solve linear system with Jacobian 3857 $ endloop 3858 3859 Notes: 3860 Matrix must already be assemblied before calling this routine 3861 Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before 3862 calling this routine. 3863 3864 When this is called multiple times it overwrites the previous set of stored values 3865 and does not allocated additional space. 3866 3867 .seealso: MatRetrieveValues() 3868 3869 @*/ 3870 PetscErrorCode MatStoreValues(Mat mat) 3871 { 3872 PetscErrorCode ierr; 3873 3874 PetscFunctionBegin; 3875 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3876 PetscCheckFalse(!mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 3877 PetscCheckFalse(mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3878 ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr); 3879 PetscFunctionReturn(0); 3880 } 3881 3882 PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat) 3883 { 3884 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3885 PetscErrorCode ierr; 3886 PetscInt nz = aij->i[mat->rmap->n]; 3887 3888 PetscFunctionBegin; 3889 PetscCheckFalse(!aij->nonew,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3890 PetscCheckFalse(!aij->saved_values,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first"); 3891 /* copy values over */ 3892 ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr); 3893 PetscFunctionReturn(0); 3894 } 3895 3896 /*@ 3897 MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 3898 example, reuse of the linear part of a Jacobian, while recomputing the 3899 nonlinear portion. 3900 3901 Collect on Mat 3902 3903 Input Parameters: 3904 . mat - the matrix (currently only AIJ matrices support this option) 3905 3906 Level: advanced 3907 3908 .seealso: MatStoreValues() 3909 3910 @*/ 3911 PetscErrorCode MatRetrieveValues(Mat mat) 3912 { 3913 PetscErrorCode ierr; 3914 3915 PetscFunctionBegin; 3916 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3917 PetscCheckFalse(!mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 3918 PetscCheckFalse(mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3919 ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr); 3920 PetscFunctionReturn(0); 3921 } 3922 3923 /* --------------------------------------------------------------------------------*/ 3924 /*@C 3925 MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format 3926 (the default parallel PETSc format). For good matrix assembly performance 3927 the user should preallocate the matrix storage by setting the parameter nz 3928 (or the array nnz). By setting these parameters accurately, performance 3929 during matrix assembly can be increased by more than a factor of 50. 3930 3931 Collective 3932 3933 Input Parameters: 3934 + comm - MPI communicator, set to PETSC_COMM_SELF 3935 . m - number of rows 3936 . n - number of columns 3937 . nz - number of nonzeros per row (same for all rows) 3938 - nnz - array containing the number of nonzeros in the various rows 3939 (possibly different for each row) or NULL 3940 3941 Output Parameter: 3942 . A - the matrix 3943 3944 It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 3945 MatXXXXSetPreallocation() paradigm instead of this routine directly. 3946 [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 3947 3948 Notes: 3949 If nnz is given then nz is ignored 3950 3951 The AIJ format (also called the Yale sparse matrix format or 3952 compressed row storage), is fully compatible with standard Fortran 77 3953 storage. That is, the stored row and column indices can begin at 3954 either one (as in Fortran) or zero. See the users' manual for details. 3955 3956 Specify the preallocated storage with either nz or nnz (not both). 3957 Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 3958 allocation. For large problems you MUST preallocate memory or you 3959 will get TERRIBLE performance, see the users' manual chapter on matrices. 3960 3961 By default, this format uses inodes (identical nodes) when possible, to 3962 improve numerical efficiency of matrix-vector products and solves. We 3963 search for consecutive rows with the same nonzero structure, thereby 3964 reusing matrix information to achieve increased efficiency. 3965 3966 Options Database Keys: 3967 + -mat_no_inode - Do not use inodes 3968 - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3969 3970 Level: intermediate 3971 3972 .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays() 3973 3974 @*/ 3975 PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A) 3976 { 3977 PetscErrorCode ierr; 3978 3979 PetscFunctionBegin; 3980 ierr = MatCreate(comm,A);CHKERRQ(ierr); 3981 ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr); 3982 ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr); 3983 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr); 3984 PetscFunctionReturn(0); 3985 } 3986 3987 /*@C 3988 MatSeqAIJSetPreallocation - For good matrix assembly performance 3989 the user should preallocate the matrix storage by setting the parameter nz 3990 (or the array nnz). By setting these parameters accurately, performance 3991 during matrix assembly can be increased by more than a factor of 50. 3992 3993 Collective 3994 3995 Input Parameters: 3996 + B - The matrix 3997 . nz - number of nonzeros per row (same for all rows) 3998 - nnz - array containing the number of nonzeros in the various rows 3999 (possibly different for each row) or NULL 4000 4001 Notes: 4002 If nnz is given then nz is ignored 4003 4004 The AIJ format (also called the Yale sparse matrix format or 4005 compressed row storage), is fully compatible with standard Fortran 77 4006 storage. That is, the stored row and column indices can begin at 4007 either one (as in Fortran) or zero. See the users' manual for details. 4008 4009 Specify the preallocated storage with either nz or nnz (not both). 4010 Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 4011 allocation. For large problems you MUST preallocate memory or you 4012 will get TERRIBLE performance, see the users' manual chapter on matrices. 4013 4014 You can call MatGetInfo() to get information on how effective the preallocation was; 4015 for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 4016 You can also run with the option -info and look for messages with the string 4017 malloc in them to see if additional memory allocation was needed. 4018 4019 Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix 4020 entries or columns indices 4021 4022 By default, this format uses inodes (identical nodes) when possible, to 4023 improve numerical efficiency of matrix-vector products and solves. We 4024 search for consecutive rows with the same nonzero structure, thereby 4025 reusing matrix information to achieve increased efficiency. 4026 4027 Options Database Keys: 4028 + -mat_no_inode - Do not use inodes 4029 - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 4030 4031 Level: intermediate 4032 4033 .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo(), 4034 MatSeqAIJSetTotalPreallocation() 4035 4036 @*/ 4037 PetscErrorCode MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[]) 4038 { 4039 PetscErrorCode ierr; 4040 4041 PetscFunctionBegin; 4042 PetscValidHeaderSpecific(B,MAT_CLASSID,1); 4043 PetscValidType(B,1); 4044 ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr); 4045 PetscFunctionReturn(0); 4046 } 4047 4048 PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz) 4049 { 4050 Mat_SeqAIJ *b; 4051 PetscBool skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE; 4052 PetscErrorCode ierr; 4053 PetscInt i; 4054 4055 PetscFunctionBegin; 4056 if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 4057 if (nz == MAT_SKIP_ALLOCATION) { 4058 skipallocation = PETSC_TRUE; 4059 nz = 0; 4060 } 4061 ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 4062 ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 4063 4064 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 4065 PetscCheckFalse(nz < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %" PetscInt_FMT,nz); 4066 if (PetscUnlikelyDebug(nnz)) { 4067 for (i=0; i<B->rmap->n; i++) { 4068 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]); 4069 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); 4070 } 4071 } 4072 4073 B->preallocated = PETSC_TRUE; 4074 4075 b = (Mat_SeqAIJ*)B->data; 4076 4077 if (!skipallocation) { 4078 if (!b->imax) { 4079 ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr); 4080 ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 4081 } 4082 if (!b->ilen) { 4083 /* b->ilen will count nonzeros in each row so far. */ 4084 ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr); 4085 ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 4086 } else { 4087 ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 4088 } 4089 if (!b->ipre) { 4090 ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr); 4091 ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 4092 } 4093 if (!nnz) { 4094 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 4095 else if (nz < 0) nz = 1; 4096 nz = PetscMin(nz,B->cmap->n); 4097 for (i=0; i<B->rmap->n; i++) b->imax[i] = nz; 4098 nz = nz*B->rmap->n; 4099 } else { 4100 PetscInt64 nz64 = 0; 4101 for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];} 4102 ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr); 4103 } 4104 4105 /* allocate the matrix space */ 4106 /* FIXME: should B's old memory be unlogged? */ 4107 ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr); 4108 if (B->structure_only) { 4109 ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr); 4110 ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr); 4111 ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr); 4112 } else { 4113 ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr); 4114 ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr); 4115 } 4116 b->i[0] = 0; 4117 for (i=1; i<B->rmap->n+1; i++) { 4118 b->i[i] = b->i[i-1] + b->imax[i-1]; 4119 } 4120 if (B->structure_only) { 4121 b->singlemalloc = PETSC_FALSE; 4122 b->free_a = PETSC_FALSE; 4123 } else { 4124 b->singlemalloc = PETSC_TRUE; 4125 b->free_a = PETSC_TRUE; 4126 } 4127 b->free_ij = PETSC_TRUE; 4128 } else { 4129 b->free_a = PETSC_FALSE; 4130 b->free_ij = PETSC_FALSE; 4131 } 4132 4133 if (b->ipre && nnz != b->ipre && b->imax) { 4134 /* reserve user-requested sparsity */ 4135 ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr); 4136 } 4137 4138 b->nz = 0; 4139 b->maxnz = nz; 4140 B->info.nz_unneeded = (double)b->maxnz; 4141 if (realalloc) { 4142 ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 4143 } 4144 B->was_assembled = PETSC_FALSE; 4145 B->assembled = PETSC_FALSE; 4146 PetscFunctionReturn(0); 4147 } 4148 4149 PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A) 4150 { 4151 Mat_SeqAIJ *a; 4152 PetscInt i; 4153 PetscErrorCode ierr; 4154 4155 PetscFunctionBegin; 4156 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 4157 4158 /* Check local size. If zero, then return */ 4159 if (!A->rmap->n) PetscFunctionReturn(0); 4160 4161 a = (Mat_SeqAIJ*)A->data; 4162 /* if no saved info, we error out */ 4163 PetscCheckFalse(!a->ipre,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info "); 4164 4165 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 "); 4166 4167 ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr); 4168 ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr); 4169 a->i[0] = 0; 4170 for (i=1; i<A->rmap->n+1; i++) { 4171 a->i[i] = a->i[i-1] + a->imax[i-1]; 4172 } 4173 A->preallocated = PETSC_TRUE; 4174 a->nz = 0; 4175 a->maxnz = a->i[A->rmap->n]; 4176 A->info.nz_unneeded = (double)a->maxnz; 4177 A->was_assembled = PETSC_FALSE; 4178 A->assembled = PETSC_FALSE; 4179 PetscFunctionReturn(0); 4180 } 4181 4182 /*@ 4183 MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format. 4184 4185 Input Parameters: 4186 + B - the matrix 4187 . i - the indices into j for the start of each row (starts with zero) 4188 . j - the column indices for each row (starts with zero) these must be sorted for each row 4189 - v - optional values in the matrix 4190 4191 Level: developer 4192 4193 Notes: 4194 The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays() 4195 4196 This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero 4197 structure will be the union of all the previous nonzero structures. 4198 4199 Developer Notes: 4200 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 4201 then just copies the v values directly with PetscMemcpy(). 4202 4203 This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them. 4204 4205 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ, MatResetPreallocation() 4206 @*/ 4207 PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[]) 4208 { 4209 PetscErrorCode ierr; 4210 4211 PetscFunctionBegin; 4212 PetscValidHeaderSpecific(B,MAT_CLASSID,1); 4213 PetscValidType(B,1); 4214 ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr); 4215 PetscFunctionReturn(0); 4216 } 4217 4218 PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[]) 4219 { 4220 PetscInt i; 4221 PetscInt m,n; 4222 PetscInt nz; 4223 PetscInt *nnz; 4224 PetscErrorCode ierr; 4225 4226 PetscFunctionBegin; 4227 PetscCheckFalse(Ii[0],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]); 4228 4229 ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 4230 ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 4231 4232 ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr); 4233 ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr); 4234 for (i = 0; i < m; i++) { 4235 nz = Ii[i+1]- Ii[i]; 4236 PetscCheckFalse(nz < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz); 4237 nnz[i] = nz; 4238 } 4239 ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr); 4240 ierr = PetscFree(nnz);CHKERRQ(ierr); 4241 4242 for (i = 0; i < m; i++) { 4243 ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr); 4244 } 4245 4246 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4247 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4248 4249 ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 4250 PetscFunctionReturn(0); 4251 } 4252 4253 /*@ 4254 MatSeqAIJKron - Computes C, the Kronecker product of A and B. 4255 4256 Input Parameters: 4257 + A - left-hand side matrix 4258 . B - right-hand side matrix 4259 - reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 4260 4261 Output Parameter: 4262 . C - Kronecker product of A and B 4263 4264 Level: intermediate 4265 4266 Notes: 4267 MAT_REUSE_MATRIX can only be used when the nonzero structure of the product matrix has not changed from that last call to MatSeqAIJKron(). 4268 4269 .seealso: MatCreateSeqAIJ(), MATSEQAIJ, MATKAIJ, MatReuse 4270 @*/ 4271 PetscErrorCode MatSeqAIJKron(Mat A,Mat B,MatReuse reuse,Mat *C) 4272 { 4273 PetscErrorCode ierr; 4274 4275 PetscFunctionBegin; 4276 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 4277 PetscValidType(A,1); 4278 PetscValidHeaderSpecific(B,MAT_CLASSID,2); 4279 PetscValidType(B,2); 4280 PetscValidPointer(C,4); 4281 if (reuse == MAT_REUSE_MATRIX) { 4282 PetscValidHeaderSpecific(*C,MAT_CLASSID,4); 4283 PetscValidType(*C,4); 4284 } 4285 ierr = PetscTryMethod(A,"MatSeqAIJKron_C",(Mat,Mat,MatReuse,Mat*),(A,B,reuse,C));CHKERRQ(ierr); 4286 PetscFunctionReturn(0); 4287 } 4288 4289 PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A,Mat B,MatReuse reuse,Mat *C) 4290 { 4291 PetscErrorCode ierr; 4292 Mat newmat; 4293 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 4294 Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 4295 PetscScalar *v; 4296 const PetscScalar *aa,*ba; 4297 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; 4298 PetscBool flg; 4299 4300 PetscFunctionBegin; 4301 PetscCheckFalse(A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 4302 PetscCheckFalse(!A->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 4303 PetscCheckFalse(B->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 4304 PetscCheckFalse(!B->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 4305 ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&flg);CHKERRQ(ierr); 4306 PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatType %s",((PetscObject)B)->type_name); 4307 PetscCheckFalse(reuse != MAT_INITIAL_MATRIX && reuse != MAT_REUSE_MATRIX,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatReuse %d",(int)reuse); 4308 if (reuse == MAT_INITIAL_MATRIX) { 4309 ierr = PetscMalloc2(am*bm+1,&i,a->i[am]*b->i[bm],&j);CHKERRQ(ierr); 4310 ierr = MatCreate(PETSC_COMM_SELF,&newmat);CHKERRQ(ierr); 4311 ierr = MatSetSizes(newmat,am*bm,an*bn,am*bm,an*bn);CHKERRQ(ierr); 4312 ierr = MatSetType(newmat,MATAIJ);CHKERRQ(ierr); 4313 i[0] = 0; 4314 for (m = 0; m < am; ++m) { 4315 for (p = 0; p < bm; ++p) { 4316 i[m*bm + p + 1] = i[m*bm + p] + (a->i[m+1] - a->i[m]) * (b->i[p+1] - b->i[p]); 4317 for (n = a->i[m]; n < a->i[m+1]; ++n) { 4318 for (q = b->i[p]; q < b->i[p+1]; ++q) { 4319 j[nnz++] = a->j[n]*bn + b->j[q]; 4320 } 4321 } 4322 } 4323 } 4324 ierr = MatSeqAIJSetPreallocationCSR(newmat,i,j,NULL);CHKERRQ(ierr); 4325 *C = newmat; 4326 ierr = PetscFree2(i,j);CHKERRQ(ierr); 4327 nnz = 0; 4328 } 4329 ierr = MatSeqAIJGetArray(*C,&v);CHKERRQ(ierr); 4330 ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr); 4331 ierr = MatSeqAIJGetArrayRead(B,&ba);CHKERRQ(ierr); 4332 for (m = 0; m < am; ++m) { 4333 for (p = 0; p < bm; ++p) { 4334 for (n = a->i[m]; n < a->i[m+1]; ++n) { 4335 for (q = b->i[p]; q < b->i[p+1]; ++q) { 4336 v[nnz++] = aa[n] * ba[q]; 4337 } 4338 } 4339 } 4340 } 4341 ierr = MatSeqAIJRestoreArray(*C,&v);CHKERRQ(ierr); 4342 ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr); 4343 ierr = MatSeqAIJRestoreArrayRead(B,&ba);CHKERRQ(ierr); 4344 PetscFunctionReturn(0); 4345 } 4346 4347 #include <../src/mat/impls/dense/seq/dense.h> 4348 #include <petsc/private/kernels/petscaxpy.h> 4349 4350 /* 4351 Computes (B'*A')' since computing B*A directly is untenable 4352 4353 n p p 4354 [ ] [ ] [ ] 4355 m [ A ] * n [ B ] = m [ C ] 4356 [ ] [ ] [ ] 4357 4358 */ 4359 PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C) 4360 { 4361 PetscErrorCode ierr; 4362 Mat_SeqDense *sub_a = (Mat_SeqDense*)A->data; 4363 Mat_SeqAIJ *sub_b = (Mat_SeqAIJ*)B->data; 4364 Mat_SeqDense *sub_c = (Mat_SeqDense*)C->data; 4365 PetscInt i,j,n,m,q,p; 4366 const PetscInt *ii,*idx; 4367 const PetscScalar *b,*a,*a_q; 4368 PetscScalar *c,*c_q; 4369 PetscInt clda = sub_c->lda; 4370 PetscInt alda = sub_a->lda; 4371 4372 PetscFunctionBegin; 4373 m = A->rmap->n; 4374 n = A->cmap->n; 4375 p = B->cmap->n; 4376 a = sub_a->v; 4377 b = sub_b->a; 4378 c = sub_c->v; 4379 if (clda == m) { 4380 ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr); 4381 } else { 4382 for (j=0;j<p;j++) 4383 for (i=0;i<m;i++) 4384 c[j*clda + i] = 0.0; 4385 } 4386 ii = sub_b->i; 4387 idx = sub_b->j; 4388 for (i=0; i<n; i++) { 4389 q = ii[i+1] - ii[i]; 4390 while (q-->0) { 4391 c_q = c + clda*(*idx); 4392 a_q = a + alda*i; 4393 PetscKernelAXPY(c_q,*b,a_q,m); 4394 idx++; 4395 b++; 4396 } 4397 } 4398 PetscFunctionReturn(0); 4399 } 4400 4401 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C) 4402 { 4403 PetscErrorCode ierr; 4404 PetscInt m=A->rmap->n,n=B->cmap->n; 4405 PetscBool cisdense; 4406 4407 PetscFunctionBegin; 4408 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); 4409 ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr); 4410 ierr = MatSetBlockSizesFromMats(C,A,B);CHKERRQ(ierr); 4411 ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr); 4412 if (!cisdense) { 4413 ierr = MatSetType(C,MATDENSE);CHKERRQ(ierr); 4414 } 4415 ierr = MatSetUp(C);CHKERRQ(ierr); 4416 4417 C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ; 4418 PetscFunctionReturn(0); 4419 } 4420 4421 /* ----------------------------------------------------------------*/ 4422 /*MC 4423 MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 4424 based on compressed sparse row format. 4425 4426 Options Database Keys: 4427 . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 4428 4429 Level: beginner 4430 4431 Notes: 4432 MatSetValues() may be called for this matrix type with a NULL argument for the numerical values, 4433 in this case the values associated with the rows and columns one passes in are set to zero 4434 in the matrix 4435 4436 MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no 4437 space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored 4438 4439 Developer Notes: 4440 It would be nice if all matrix formats supported passing NULL in for the numerical values 4441 4442 .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType, MATSELL, MATSEQSELL, MATMPISELL 4443 M*/ 4444 4445 /*MC 4446 MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 4447 4448 This matrix type is identical to MATSEQAIJ when constructed with a single process communicator, 4449 and MATMPIAIJ otherwise. As a result, for single process communicators, 4450 MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 4451 for communicators controlling multiple processes. It is recommended that you call both of 4452 the above preallocation routines for simplicity. 4453 4454 Options Database Keys: 4455 . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions() 4456 4457 Developer Notes: 4458 Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when 4459 enough exist. 4460 4461 Level: beginner 4462 4463 .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ, MATMPIAIJ, MATSELL, MATSEQSELL, MATMPISELL 4464 M*/ 4465 4466 /*MC 4467 MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 4468 4469 This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator, 4470 and MATMPIAIJCRL otherwise. As a result, for single process communicators, 4471 MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 4472 for communicators controlling multiple processes. It is recommended that you call both of 4473 the above preallocation routines for simplicity. 4474 4475 Options Database Keys: 4476 . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions() 4477 4478 Level: beginner 4479 4480 .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL 4481 M*/ 4482 4483 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*); 4484 #if defined(PETSC_HAVE_ELEMENTAL) 4485 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*); 4486 #endif 4487 #if defined(PETSC_HAVE_SCALAPACK) 4488 PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*); 4489 #endif 4490 #if defined(PETSC_HAVE_HYPRE) 4491 PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*); 4492 #endif 4493 4494 PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*); 4495 PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*); 4496 PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat); 4497 4498 /*@C 4499 MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored 4500 4501 Not Collective 4502 4503 Input Parameter: 4504 . mat - a MATSEQAIJ matrix 4505 4506 Output Parameter: 4507 . array - pointer to the data 4508 4509 Level: intermediate 4510 4511 .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90() 4512 @*/ 4513 PetscErrorCode MatSeqAIJGetArray(Mat A,PetscScalar **array) 4514 { 4515 PetscErrorCode ierr; 4516 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4517 4518 PetscFunctionBegin; 4519 if (aij->ops->getarray) { 4520 ierr = (*aij->ops->getarray)(A,array);CHKERRQ(ierr); 4521 } else { 4522 *array = aij->a; 4523 } 4524 PetscFunctionReturn(0); 4525 } 4526 4527 /*@C 4528 MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray() 4529 4530 Not Collective 4531 4532 Input Parameters: 4533 + mat - a MATSEQAIJ matrix 4534 - array - pointer to the data 4535 4536 Level: intermediate 4537 4538 .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90() 4539 @*/ 4540 PetscErrorCode MatSeqAIJRestoreArray(Mat A,PetscScalar **array) 4541 { 4542 PetscErrorCode ierr; 4543 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4544 4545 PetscFunctionBegin; 4546 if (aij->ops->restorearray) { 4547 ierr = (*aij->ops->restorearray)(A,array);CHKERRQ(ierr); 4548 } else { 4549 *array = NULL; 4550 } 4551 ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr); 4552 ierr = PetscObjectStateIncrease((PetscObject)A);CHKERRQ(ierr); 4553 PetscFunctionReturn(0); 4554 } 4555 4556 /*@C 4557 MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored 4558 4559 Not Collective 4560 4561 Input Parameter: 4562 . mat - a MATSEQAIJ matrix 4563 4564 Output Parameter: 4565 . array - pointer to the data 4566 4567 Level: intermediate 4568 4569 .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead() 4570 @*/ 4571 PetscErrorCode MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array) 4572 { 4573 PetscErrorCode ierr; 4574 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4575 4576 PetscFunctionBegin; 4577 if (aij->ops->getarrayread) { 4578 ierr = (*aij->ops->getarrayread)(A,array);CHKERRQ(ierr); 4579 } else { 4580 *array = aij->a; 4581 } 4582 PetscFunctionReturn(0); 4583 } 4584 4585 /*@C 4586 MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead 4587 4588 Not Collective 4589 4590 Input Parameter: 4591 . mat - a MATSEQAIJ matrix 4592 4593 Output Parameter: 4594 . array - pointer to the data 4595 4596 Level: intermediate 4597 4598 .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead() 4599 @*/ 4600 PetscErrorCode MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array) 4601 { 4602 PetscErrorCode ierr; 4603 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4604 4605 PetscFunctionBegin; 4606 if (aij->ops->restorearrayread) { 4607 ierr = (*aij->ops->restorearrayread)(A,array);CHKERRQ(ierr); 4608 } else { 4609 *array = NULL; 4610 } 4611 PetscFunctionReturn(0); 4612 } 4613 4614 /*@C 4615 MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a MATSEQAIJ matrix is stored 4616 4617 Not Collective 4618 4619 Input Parameter: 4620 . mat - a MATSEQAIJ matrix 4621 4622 Output Parameter: 4623 . array - pointer to the data 4624 4625 Level: intermediate 4626 4627 .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead() 4628 @*/ 4629 PetscErrorCode MatSeqAIJGetArrayWrite(Mat A,PetscScalar **array) 4630 { 4631 PetscErrorCode ierr; 4632 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4633 4634 PetscFunctionBegin; 4635 if (aij->ops->getarraywrite) { 4636 ierr = (*aij->ops->getarraywrite)(A,array);CHKERRQ(ierr); 4637 } else { 4638 *array = aij->a; 4639 } 4640 ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr); 4641 ierr = PetscObjectStateIncrease((PetscObject)A);CHKERRQ(ierr); 4642 PetscFunctionReturn(0); 4643 } 4644 4645 /*@C 4646 MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead 4647 4648 Not Collective 4649 4650 Input Parameter: 4651 . mat - a MATSEQAIJ matrix 4652 4653 Output Parameter: 4654 . array - pointer to the data 4655 4656 Level: intermediate 4657 4658 .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead() 4659 @*/ 4660 PetscErrorCode MatSeqAIJRestoreArrayWrite(Mat A,PetscScalar **array) 4661 { 4662 PetscErrorCode ierr; 4663 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4664 4665 PetscFunctionBegin; 4666 if (aij->ops->restorearraywrite) { 4667 ierr = (*aij->ops->restorearraywrite)(A,array);CHKERRQ(ierr); 4668 } else { 4669 *array = NULL; 4670 } 4671 PetscFunctionReturn(0); 4672 } 4673 4674 /*@C 4675 MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row 4676 4677 Not Collective 4678 4679 Input Parameter: 4680 . mat - a MATSEQAIJ matrix 4681 4682 Output Parameter: 4683 . nz - the maximum number of nonzeros in any row 4684 4685 Level: intermediate 4686 4687 .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90() 4688 @*/ 4689 PetscErrorCode MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz) 4690 { 4691 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4692 4693 PetscFunctionBegin; 4694 *nz = aij->rmax; 4695 PetscFunctionReturn(0); 4696 } 4697 4698 PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, const PetscInt coo_i[], const PetscInt coo_j[]) 4699 { 4700 PetscErrorCode ierr; 4701 MPI_Comm comm; 4702 PetscInt *i,*j; 4703 PetscInt M,N,row; 4704 PetscCount k,p,q,nneg,nnz,start,end; /* Index the coo array, so use PetscCount as their type */ 4705 PetscInt *Ai; /* Change to PetscCount once we use it for row pointers */ 4706 PetscInt *Aj; 4707 PetscScalar *Aa; 4708 Mat_SeqAIJ *seqaij; 4709 Mat newmat; 4710 PetscCount *perm,*jmap; 4711 4712 PetscFunctionBegin; 4713 ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 4714 ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 4715 ierr = PetscMalloc2(coo_n,&i,coo_n,&j);CHKERRQ(ierr); 4716 ierr = PetscArraycpy(i,coo_i,coo_n);CHKERRQ(ierr); /* Make a copy since we'll modify it */ 4717 ierr = PetscArraycpy(j,coo_j,coo_n);CHKERRQ(ierr); 4718 ierr = PetscMalloc1(coo_n,&perm);CHKERRQ(ierr); 4719 for (k=0; k<coo_n; k++) { /* Ignore entries with negative row or col indices */ 4720 if (j[k] < 0) i[k] = -1; 4721 perm[k] = k; 4722 } 4723 4724 /* Sort by row */ 4725 ierr = PetscSortIntWithIntCountArrayPair(coo_n,i,j,perm);CHKERRQ(ierr); 4726 for (k=0; k<coo_n; k++) {if (i[k] >= 0) break;} /* Advance k to the first row with a non-negative index */ 4727 nneg = k; 4728 ierr = PetscMalloc1(coo_n-nneg+1,&jmap);CHKERRQ(ierr); /* +1 to make a CSR-like data structure. jmap[i] originally is the number of repeats for i-th nonzero */ 4729 nnz = 0; /* Total number of unique nonzeros to be counted */ 4730 jmap++; /* Inc jmap by 1 for convinience */ 4731 4732 ierr = PetscCalloc1(M+1,&Ai);CHKERRQ(ierr); /* CSR of A */ 4733 ierr = PetscMalloc1(coo_n-nneg,&Aj);CHKERRQ(ierr); /* We have at most coo_n-nneg unique nonzeros */ 4734 4735 /* In each row, sort by column, then unique column indices to get row length */ 4736 Ai++; /* Inc by 1 for convinience */ 4737 q = 0; /* q-th unique nonzero, with q starting from 0 */ 4738 while (k<coo_n) { 4739 row = i[k]; 4740 start = k; /* [start,end) indices for this row */ 4741 while (k<coo_n && i[k] == row) k++; 4742 end = k; 4743 ierr = PetscSortIntWithCountArray(end-start,j+start,perm+start);CHKERRQ(ierr); 4744 /* Find number of unique col entries in this row */ 4745 Aj[q] = j[start]; /* Log the first nonzero in this row */ 4746 jmap[q] = 1; /* Number of repeats of this nozero entry */ 4747 Ai[row] = 1; 4748 nnz++; 4749 4750 for (p=start+1; p<end; p++) { /* Scan remaining nonzero in this row */ 4751 if (j[p] != j[p-1]) { /* Meet a new nonzero */ 4752 q++; 4753 jmap[q] = 1; 4754 Aj[q] = j[p]; 4755 Ai[row]++; 4756 nnz++; 4757 } else { 4758 jmap[q]++; 4759 } 4760 } 4761 q++; /* Move to next row and thus next unique nonzero */ 4762 } 4763 ierr = PetscFree2(i,j);CHKERRQ(ierr); 4764 4765 Ai--; /* Back to the beginning of Ai[] */ 4766 for (k=0; k<M; k++) Ai[k+1] += Ai[k]; 4767 jmap--; /* Back to the beginning of jmap[] */ 4768 jmap[0] = 0; 4769 for (k=0; k<nnz; k++) jmap[k+1] += jmap[k]; 4770 if (nnz < coo_n-nneg) { /* Realloc with actual number of unique nonzeros */ 4771 PetscCount *jmap_new; 4772 PetscInt *Aj_new; 4773 4774 ierr = PetscMalloc1(nnz+1,&jmap_new);CHKERRQ(ierr); 4775 ierr = PetscArraycpy(jmap_new,jmap,nnz+1);CHKERRQ(ierr); 4776 ierr = PetscFree(jmap);CHKERRQ(ierr); 4777 jmap = jmap_new; 4778 4779 ierr = PetscMalloc1(nnz,&Aj_new);CHKERRQ(ierr); 4780 ierr = PetscArraycpy(Aj_new,Aj,nnz);CHKERRQ(ierr); 4781 ierr = PetscFree(Aj);CHKERRQ(ierr); 4782 Aj = Aj_new; 4783 } 4784 4785 if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */ 4786 PetscCount *perm_new; 4787 ierr = PetscMalloc1(coo_n-nneg,&perm_new);CHKERRQ(ierr); 4788 ierr = PetscArraycpy(perm_new,perm+nneg,coo_n-nneg);CHKERRQ(ierr); 4789 ierr = PetscFree(perm);CHKERRQ(ierr); 4790 perm = perm_new; 4791 } 4792 4793 ierr = PetscCalloc1(nnz,&Aa);CHKERRQ(ierr); /* Zero the matrix */ 4794 ierr = MatCreateSeqAIJWithArrays(comm,M,N,Ai,Aj,Aa,&newmat);CHKERRQ(ierr); 4795 ierr = MatHeaderMerge(mat,&newmat);CHKERRQ(ierr); 4796 4797 seqaij = (Mat_SeqAIJ*)(mat->data); 4798 seqaij->singlemalloc = PETSC_FALSE; /* Ai, Aj and Aa are not allocated in one big malloc */ 4799 seqaij->free_a = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */ 4800 /* Record COO fields */ 4801 seqaij->coo_n = coo_n; 4802 seqaij->Atot = coo_n-nneg; /* Annz is seqaij->nz, so no need to record that again */ 4803 seqaij->jmap = jmap; /* of length nnz+1 */ 4804 seqaij->perm = perm; 4805 PetscFunctionReturn(0); 4806 } 4807 4808 static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A,const PetscScalar v[],InsertMode imode) 4809 { 4810 PetscErrorCode ierr; 4811 Mat_SeqAIJ *aseq = (Mat_SeqAIJ*)A->data; 4812 PetscCount i,j,Annz = aseq->nz; 4813 PetscCount *perm = aseq->perm,*jmap = aseq->jmap; 4814 PetscScalar *Aa; 4815 4816 PetscFunctionBegin; 4817 ierr = MatSeqAIJGetArray(A,&Aa);CHKERRQ(ierr); 4818 for (i=0; i<Annz; i++) { 4819 PetscScalar sum = 0.0; 4820 for (j=jmap[i]; j<jmap[i+1]; j++) sum += v[perm[j]]; 4821 Aa[i] = (imode == INSERT_VALUES? 0.0 : Aa[i]) + sum; 4822 } 4823 ierr = MatSeqAIJRestoreArray(A,&Aa);CHKERRQ(ierr); 4824 PetscFunctionReturn(0); 4825 } 4826 4827 #if defined(PETSC_HAVE_CUDA) 4828 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat,MatType,MatReuse,Mat*); 4829 #endif 4830 #if defined(PETSC_HAVE_KOKKOS_KERNELS) 4831 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat,MatType,MatReuse,Mat*); 4832 #endif 4833 4834 PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B) 4835 { 4836 Mat_SeqAIJ *b; 4837 PetscErrorCode ierr; 4838 PetscMPIInt size; 4839 4840 PetscFunctionBegin; 4841 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRMPI(ierr); 4842 PetscCheckFalse(size > 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1"); 4843 4844 ierr = PetscNewLog(B,&b);CHKERRQ(ierr); 4845 4846 B->data = (void*)b; 4847 4848 ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 4849 if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 4850 4851 b->row = NULL; 4852 b->col = NULL; 4853 b->icol = NULL; 4854 b->reallocs = 0; 4855 b->ignorezeroentries = PETSC_FALSE; 4856 b->roworiented = PETSC_TRUE; 4857 b->nonew = 0; 4858 b->diag = NULL; 4859 b->solve_work = NULL; 4860 B->spptr = NULL; 4861 b->saved_values = NULL; 4862 b->idiag = NULL; 4863 b->mdiag = NULL; 4864 b->ssor_work = NULL; 4865 b->omega = 1.0; 4866 b->fshift = 0.0; 4867 b->idiagvalid = PETSC_FALSE; 4868 b->ibdiagvalid = PETSC_FALSE; 4869 b->keepnonzeropattern = PETSC_FALSE; 4870 4871 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 4872 4873 #if defined(PETSC_HAVE_MATLAB_ENGINE) 4874 ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr); 4875 ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr); 4876 #endif 4877 4878 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr); 4879 ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr); 4880 ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr); 4881 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr); 4882 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr); 4883 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr); 4884 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr); 4885 #if defined(PETSC_HAVE_MKL_SPARSE) 4886 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr); 4887 #endif 4888 #if defined(PETSC_HAVE_CUDA) 4889 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr); 4890 ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr); 4891 ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr); 4892 #endif 4893 #if defined(PETSC_HAVE_KOKKOS_KERNELS) 4894 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr); 4895 #endif 4896 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr); 4897 #if defined(PETSC_HAVE_ELEMENTAL) 4898 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr); 4899 #endif 4900 #if defined(PETSC_HAVE_SCALAPACK) 4901 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK);CHKERRQ(ierr); 4902 #endif 4903 #if defined(PETSC_HAVE_HYPRE) 4904 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr); 4905 ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ);CHKERRQ(ierr); 4906 #endif 4907 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr); 4908 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr); 4909 ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr); 4910 ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr); 4911 ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr); 4912 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr); 4913 ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr); 4914 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr); 4915 ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr); 4916 ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ);CHKERRQ(ierr); 4917 ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ);CHKERRQ(ierr); 4918 ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr); 4919 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJKron_C",MatSeqAIJKron_SeqAIJ);CHKERRQ(ierr); 4920 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSetPreallocationCOO_C",MatSetPreallocationCOO_SeqAIJ);CHKERRQ(ierr); 4921 ierr = PetscObjectComposeFunction((PetscObject)B,"MatSetValuesCOO_C",MatSetValuesCOO_SeqAIJ);CHKERRQ(ierr); 4922 ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr); 4923 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 4924 ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr); /* this allows changing the matrix subtype to say MATSEQAIJPERM */ 4925 PetscFunctionReturn(0); 4926 } 4927 4928 /* 4929 Given a matrix generated with MatGetFactor() duplicates all the information in A into B 4930 */ 4931 PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace) 4932 { 4933 Mat_SeqAIJ *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data; 4934 PetscErrorCode ierr; 4935 PetscInt m = A->rmap->n,i; 4936 4937 PetscFunctionBegin; 4938 PetscCheckFalse(!A->assembled && cpvalues!=MAT_DO_NOT_COPY_VALUES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix"); 4939 4940 C->factortype = A->factortype; 4941 c->row = NULL; 4942 c->col = NULL; 4943 c->icol = NULL; 4944 c->reallocs = 0; 4945 4946 C->assembled = PETSC_TRUE; 4947 4948 ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr); 4949 ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr); 4950 4951 ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr); 4952 ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr); 4953 ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr); 4954 ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr); 4955 ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr); 4956 4957 /* allocate the matrix space */ 4958 if (mallocmatspace) { 4959 ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr); 4960 ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 4961 4962 c->singlemalloc = PETSC_TRUE; 4963 4964 ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr); 4965 if (m > 0) { 4966 ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr); 4967 if (cpvalues == MAT_COPY_VALUES) { 4968 const PetscScalar *aa; 4969 4970 ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr); 4971 ierr = PetscArraycpy(c->a,aa,a->i[m]);CHKERRQ(ierr); 4972 ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr); 4973 } else { 4974 ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr); 4975 } 4976 } 4977 } 4978 4979 c->ignorezeroentries = a->ignorezeroentries; 4980 c->roworiented = a->roworiented; 4981 c->nonew = a->nonew; 4982 if (a->diag) { 4983 ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr); 4984 ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr); 4985 ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 4986 } else c->diag = NULL; 4987 4988 c->solve_work = NULL; 4989 c->saved_values = NULL; 4990 c->idiag = NULL; 4991 c->ssor_work = NULL; 4992 c->keepnonzeropattern = a->keepnonzeropattern; 4993 c->free_a = PETSC_TRUE; 4994 c->free_ij = PETSC_TRUE; 4995 4996 c->rmax = a->rmax; 4997 c->nz = a->nz; 4998 c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 4999 C->preallocated = PETSC_TRUE; 5000 5001 c->compressedrow.use = a->compressedrow.use; 5002 c->compressedrow.nrows = a->compressedrow.nrows; 5003 if (a->compressedrow.use) { 5004 i = a->compressedrow.nrows; 5005 ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr); 5006 ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr); 5007 ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr); 5008 } else { 5009 c->compressedrow.use = PETSC_FALSE; 5010 c->compressedrow.i = NULL; 5011 c->compressedrow.rindex = NULL; 5012 } 5013 c->nonzerorowcnt = a->nonzerorowcnt; 5014 C->nonzerostate = A->nonzerostate; 5015 5016 ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr); 5017 ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr); 5018 PetscFunctionReturn(0); 5019 } 5020 5021 PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B) 5022 { 5023 PetscErrorCode ierr; 5024 5025 PetscFunctionBegin; 5026 ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr); 5027 ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr); 5028 if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) { 5029 ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr); 5030 } 5031 ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr); 5032 ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr); 5033 PetscFunctionReturn(0); 5034 } 5035 5036 PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer) 5037 { 5038 PetscBool isbinary, ishdf5; 5039 PetscErrorCode ierr; 5040 5041 PetscFunctionBegin; 5042 PetscValidHeaderSpecific(newMat,MAT_CLASSID,1); 5043 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 5044 /* force binary viewer to load .info file if it has not yet done so */ 5045 ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr); 5046 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 5047 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 5048 if (isbinary) { 5049 ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr); 5050 } else if (ishdf5) { 5051 #if defined(PETSC_HAVE_HDF5) 5052 ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr); 5053 #else 5054 SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 5055 #endif 5056 } else { 5057 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); 5058 } 5059 PetscFunctionReturn(0); 5060 } 5061 5062 PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer) 5063 { 5064 Mat_SeqAIJ *a = (Mat_SeqAIJ*)mat->data; 5065 PetscErrorCode ierr; 5066 PetscInt header[4],*rowlens,M,N,nz,sum,rows,cols,i; 5067 5068 PetscFunctionBegin; 5069 ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr); 5070 5071 /* read in matrix header */ 5072 ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr); 5073 PetscCheckFalse(header[0] != MAT_FILE_CLASSID,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file"); 5074 M = header[1]; N = header[2]; nz = header[3]; 5075 PetscCheckFalse(M < 0,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%" PetscInt_FMT ") in file is negative",M); 5076 PetscCheckFalse(N < 0,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%" PetscInt_FMT ") in file is negative",N); 5077 PetscCheckFalse(nz < 0,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ"); 5078 5079 /* set block sizes from the viewer's .info file */ 5080 ierr = MatLoad_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr); 5081 /* set local and global sizes if not set already */ 5082 if (mat->rmap->n < 0) mat->rmap->n = M; 5083 if (mat->cmap->n < 0) mat->cmap->n = N; 5084 if (mat->rmap->N < 0) mat->rmap->N = M; 5085 if (mat->cmap->N < 0) mat->cmap->N = N; 5086 ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr); 5087 ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr); 5088 5089 /* check if the matrix sizes are correct */ 5090 ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr); 5091 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); 5092 5093 /* read in row lengths */ 5094 ierr = PetscMalloc1(M,&rowlens);CHKERRQ(ierr); 5095 ierr = PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT);CHKERRQ(ierr); 5096 /* check if sum(rowlens) is same as nz */ 5097 sum = 0; for (i=0; i<M; i++) sum += rowlens[i]; 5098 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); 5099 /* preallocate and check sizes */ 5100 ierr = MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens);CHKERRQ(ierr); 5101 ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr); 5102 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); 5103 /* store row lengths */ 5104 ierr = PetscArraycpy(a->ilen,rowlens,M);CHKERRQ(ierr); 5105 ierr = PetscFree(rowlens);CHKERRQ(ierr); 5106 5107 /* fill in "i" row pointers */ 5108 a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i]; 5109 /* read in "j" column indices */ 5110 ierr = PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr); 5111 /* read in "a" nonzero values */ 5112 ierr = PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr); 5113 5114 ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 5115 ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 5116 PetscFunctionReturn(0); 5117 } 5118 5119 PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg) 5120 { 5121 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data; 5122 PetscErrorCode ierr; 5123 const PetscScalar *aa,*ba; 5124 #if defined(PETSC_USE_COMPLEX) 5125 PetscInt k; 5126 #endif 5127 5128 PetscFunctionBegin; 5129 /* If the matrix dimensions are not equal,or no of nonzeros */ 5130 if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) { 5131 *flg = PETSC_FALSE; 5132 PetscFunctionReturn(0); 5133 } 5134 5135 /* if the a->i are the same */ 5136 ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr); 5137 if (!*flg) PetscFunctionReturn(0); 5138 5139 /* if a->j are the same */ 5140 ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr); 5141 if (!*flg) PetscFunctionReturn(0); 5142 5143 ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr); 5144 ierr = MatSeqAIJGetArrayRead(B,&ba);CHKERRQ(ierr); 5145 /* if a->a are the same */ 5146 #if defined(PETSC_USE_COMPLEX) 5147 for (k=0; k<a->nz; k++) { 5148 if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) { 5149 *flg = PETSC_FALSE; 5150 PetscFunctionReturn(0); 5151 } 5152 } 5153 #else 5154 ierr = PetscArraycmp(aa,ba,a->nz,flg);CHKERRQ(ierr); 5155 #endif 5156 ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr); 5157 ierr = MatSeqAIJRestoreArrayRead(B,&ba);CHKERRQ(ierr); 5158 PetscFunctionReturn(0); 5159 } 5160 5161 /*@ 5162 MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format) 5163 provided by the user. 5164 5165 Collective 5166 5167 Input Parameters: 5168 + comm - must be an MPI communicator of size 1 5169 . m - number of rows 5170 . n - number of columns 5171 . i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 5172 . j - column indices 5173 - a - matrix values 5174 5175 Output Parameter: 5176 . mat - the matrix 5177 5178 Level: intermediate 5179 5180 Notes: 5181 The i, j, and a arrays are not copied by this routine, the user must free these arrays 5182 once the matrix is destroyed and not before 5183 5184 You cannot set new nonzero locations into this matrix, that will generate an error. 5185 5186 The i and j indices are 0 based 5187 5188 The format which is used for the sparse matrix input, is equivalent to a 5189 row-major ordering.. i.e for the following matrix, the input data expected is 5190 as shown 5191 5192 $ 1 0 0 5193 $ 2 0 3 5194 $ 4 5 6 5195 $ 5196 $ i = {0,1,3,6} [size = nrow+1 = 3+1] 5197 $ j = {0,0,2,0,1,2} [size = 6]; values must be sorted for each row 5198 $ v = {1,2,3,4,5,6} [size = 6] 5199 5200 .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR() 5201 5202 @*/ 5203 PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat) 5204 { 5205 PetscErrorCode ierr; 5206 PetscInt ii; 5207 Mat_SeqAIJ *aij; 5208 PetscInt jj; 5209 5210 PetscFunctionBegin; 5211 PetscCheckFalse(m > 0 && i[0],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 5212 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 5213 ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr); 5214 /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */ 5215 ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr); 5216 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL);CHKERRQ(ierr); 5217 aij = (Mat_SeqAIJ*)(*mat)->data; 5218 ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr); 5219 ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr); 5220 5221 aij->i = i; 5222 aij->j = j; 5223 aij->a = a; 5224 aij->singlemalloc = PETSC_FALSE; 5225 aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 5226 aij->free_a = PETSC_FALSE; 5227 aij->free_ij = PETSC_FALSE; 5228 5229 for (ii=0; ii<m; ii++) { 5230 aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii]; 5231 if (PetscDefined(USE_DEBUG)) { 5232 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]); 5233 for (jj=i[ii]+1; jj<i[ii+1]; jj++) { 5234 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); 5235 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); 5236 } 5237 } 5238 } 5239 if (PetscDefined(USE_DEBUG)) { 5240 for (ii=0; ii<aij->i[m]; ii++) { 5241 PetscCheckFalse(j[ii] < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %" PetscInt_FMT " index = %" PetscInt_FMT,ii,j[ii]); 5242 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]); 5243 } 5244 } 5245 5246 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 5247 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 5248 PetscFunctionReturn(0); 5249 } 5250 /*@C 5251 MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format) 5252 provided by the user. 5253 5254 Collective 5255 5256 Input Parameters: 5257 + comm - must be an MPI communicator of size 1 5258 . m - number of rows 5259 . n - number of columns 5260 . i - row indices 5261 . j - column indices 5262 . a - matrix values 5263 . nz - number of nonzeros 5264 - idx - 0 or 1 based 5265 5266 Output Parameter: 5267 . mat - the matrix 5268 5269 Level: intermediate 5270 5271 Notes: 5272 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, 5273 the input data expected is as shown 5274 .vb 5275 1 0 0 5276 2 0 3 5277 4 5 6 5278 5279 i = {0,1,1,2,2,2} 5280 j = {0,0,2,0,1,2} 5281 v = {1,2,3,4,5,6} 5282 .ve 5283 5284 .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR() 5285 5286 @*/ 5287 PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx) 5288 { 5289 PetscErrorCode ierr; 5290 PetscInt ii, *nnz, one = 1,row,col; 5291 5292 PetscFunctionBegin; 5293 ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr); 5294 for (ii = 0; ii < nz; ii++) { 5295 nnz[i[ii] - !!idx] += 1; 5296 } 5297 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 5298 ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr); 5299 ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr); 5300 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr); 5301 for (ii = 0; ii < nz; ii++) { 5302 if (idx) { 5303 row = i[ii] - 1; 5304 col = j[ii] - 1; 5305 } else { 5306 row = i[ii]; 5307 col = j[ii]; 5308 } 5309 ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr); 5310 } 5311 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 5312 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 5313 ierr = PetscFree(nnz);CHKERRQ(ierr); 5314 PetscFunctionReturn(0); 5315 } 5316 5317 PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A) 5318 { 5319 Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data; 5320 PetscErrorCode ierr; 5321 5322 PetscFunctionBegin; 5323 a->idiagvalid = PETSC_FALSE; 5324 a->ibdiagvalid = PETSC_FALSE; 5325 5326 ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr); 5327 PetscFunctionReturn(0); 5328 } 5329 5330 PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat) 5331 { 5332 PetscErrorCode ierr; 5333 PetscMPIInt size; 5334 5335 PetscFunctionBegin; 5336 ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr); 5337 if (size == 1) { 5338 if (scall == MAT_INITIAL_MATRIX) { 5339 ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr); 5340 } else { 5341 ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 5342 } 5343 } else { 5344 ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr); 5345 } 5346 PetscFunctionReturn(0); 5347 } 5348 5349 /* 5350 Permute A into C's *local* index space using rowemb,colemb. 5351 The embedding are supposed to be injections and the above implies that the range of rowemb is a subset 5352 of [0,m), colemb is in [0,n). 5353 If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A. 5354 */ 5355 PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B) 5356 { 5357 /* If making this function public, change the error returned in this function away from _PLIB. */ 5358 PetscErrorCode ierr; 5359 Mat_SeqAIJ *Baij; 5360 PetscBool seqaij; 5361 PetscInt m,n,*nz,i,j,count; 5362 PetscScalar v; 5363 const PetscInt *rowindices,*colindices; 5364 5365 PetscFunctionBegin; 5366 if (!B) PetscFunctionReturn(0); 5367 /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */ 5368 ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr); 5369 PetscCheckFalse(!seqaij,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type"); 5370 if (rowemb) { 5371 ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr); 5372 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); 5373 } else { 5374 PetscCheckFalse(C->rmap->n != B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix"); 5375 } 5376 if (colemb) { 5377 ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr); 5378 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); 5379 } else { 5380 PetscCheckFalse(C->cmap->n != B->cmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix"); 5381 } 5382 5383 Baij = (Mat_SeqAIJ*)(B->data); 5384 if (pattern == DIFFERENT_NONZERO_PATTERN) { 5385 ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr); 5386 for (i=0; i<B->rmap->n; i++) { 5387 nz[i] = Baij->i[i+1] - Baij->i[i]; 5388 } 5389 ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr); 5390 ierr = PetscFree(nz);CHKERRQ(ierr); 5391 } 5392 if (pattern == SUBSET_NONZERO_PATTERN) { 5393 ierr = MatZeroEntries(C);CHKERRQ(ierr); 5394 } 5395 count = 0; 5396 rowindices = NULL; 5397 colindices = NULL; 5398 if (rowemb) { 5399 ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr); 5400 } 5401 if (colemb) { 5402 ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr); 5403 } 5404 for (i=0; i<B->rmap->n; i++) { 5405 PetscInt row; 5406 row = i; 5407 if (rowindices) row = rowindices[i]; 5408 for (j=Baij->i[i]; j<Baij->i[i+1]; j++) { 5409 PetscInt col; 5410 col = Baij->j[count]; 5411 if (colindices) col = colindices[col]; 5412 v = Baij->a[count]; 5413 ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr); 5414 ++count; 5415 } 5416 } 5417 /* FIXME: set C's nonzerostate correctly. */ 5418 /* Assembly for C is necessary. */ 5419 C->preallocated = PETSC_TRUE; 5420 C->assembled = PETSC_TRUE; 5421 C->was_assembled = PETSC_FALSE; 5422 PetscFunctionReturn(0); 5423 } 5424 5425 PetscFunctionList MatSeqAIJList = NULL; 5426 5427 /*@C 5428 MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype 5429 5430 Collective on Mat 5431 5432 Input Parameters: 5433 + mat - the matrix object 5434 - matype - matrix type 5435 5436 Options Database Key: 5437 . -mat_seqai_type <method> - for example seqaijcrl 5438 5439 Level: intermediate 5440 5441 .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat 5442 @*/ 5443 PetscErrorCode MatSeqAIJSetType(Mat mat, MatType matype) 5444 { 5445 PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*); 5446 PetscBool sametype; 5447 5448 PetscFunctionBegin; 5449 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 5450 ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr); 5451 if (sametype) PetscFunctionReturn(0); 5452 5453 ierr = PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr); 5454 PetscCheckFalse(!r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype); 5455 ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr); 5456 PetscFunctionReturn(0); 5457 } 5458 5459 /*@C 5460 MatSeqAIJRegister - - Adds a new sub-matrix type for sequential AIJ matrices 5461 5462 Not Collective 5463 5464 Input Parameters: 5465 + name - name of a new user-defined matrix type, for example MATSEQAIJCRL 5466 - function - routine to convert to subtype 5467 5468 Notes: 5469 MatSeqAIJRegister() may be called multiple times to add several user-defined solvers. 5470 5471 Then, your matrix can be chosen with the procedural interface at runtime via the option 5472 $ -mat_seqaij_type my_mat 5473 5474 Level: advanced 5475 5476 .seealso: MatSeqAIJRegisterAll() 5477 5478 Level: advanced 5479 @*/ 5480 PetscErrorCode MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *)) 5481 { 5482 PetscErrorCode ierr; 5483 5484 PetscFunctionBegin; 5485 ierr = MatInitializePackage();CHKERRQ(ierr); 5486 ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr); 5487 PetscFunctionReturn(0); 5488 } 5489 5490 PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE; 5491 5492 /*@C 5493 MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ 5494 5495 Not Collective 5496 5497 Level: advanced 5498 5499 .seealso: MatRegisterAll(), MatSeqAIJRegister() 5500 @*/ 5501 PetscErrorCode MatSeqAIJRegisterAll(void) 5502 { 5503 PetscErrorCode ierr; 5504 5505 PetscFunctionBegin; 5506 if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0); 5507 MatSeqAIJRegisterAllCalled = PETSC_TRUE; 5508 5509 ierr = MatSeqAIJRegister(MATSEQAIJCRL, MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr); 5510 ierr = MatSeqAIJRegister(MATSEQAIJPERM, MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr); 5511 ierr = MatSeqAIJRegister(MATSEQAIJSELL, MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr); 5512 #if defined(PETSC_HAVE_MKL_SPARSE) 5513 ierr = MatSeqAIJRegister(MATSEQAIJMKL, MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr); 5514 #endif 5515 #if defined(PETSC_HAVE_CUDA) 5516 ierr = MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr); 5517 #endif 5518 #if defined(PETSC_HAVE_KOKKOS_KERNELS) 5519 ierr = MatSeqAIJRegister(MATSEQAIJKOKKOS, MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr); 5520 #endif 5521 #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA) 5522 ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr); 5523 #endif 5524 PetscFunctionReturn(0); 5525 } 5526 5527 /* 5528 Special version for direct calls from Fortran 5529 */ 5530 #include <petsc/private/fortranimpl.h> 5531 #if defined(PETSC_HAVE_FORTRAN_CAPS) 5532 #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ 5533 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 5534 #define matsetvaluesseqaij_ matsetvaluesseqaij 5535 #endif 5536 5537 /* Change these macros so can be used in void function */ 5538 5539 /* Change these macros so can be used in void function */ 5540 /* Identical to CHKERRV, except it assigns to *_ierr */ 5541 #undef CHKERRQ 5542 #define CHKERRQ(ierr) do { \ 5543 PetscErrorCode ierr_msv_mpiaij = (ierr); \ 5544 if (PetscUnlikely(ierr_msv_mpiaij)) { \ 5545 *_ierr = PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,ierr_msv_mpiaij,PETSC_ERROR_REPEAT," "); \ 5546 return; \ 5547 } \ 5548 } while (0) 5549 5550 #undef SETERRQ 5551 #define SETERRQ(comm,ierr,...) do { \ 5552 *_ierr = PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,ierr,PETSC_ERROR_INITIAL,__VA_ARGS__); \ 5553 return; \ 5554 } while (0) 5555 5556 PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr) 5557 { 5558 Mat A = *AA; 5559 PetscInt m = *mm, n = *nn; 5560 InsertMode is = *isis; 5561 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 5562 PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N; 5563 PetscInt *imax,*ai,*ailen; 5564 PetscErrorCode ierr; 5565 PetscInt *aj,nonew = a->nonew,lastcol = -1; 5566 MatScalar *ap,value,*aa; 5567 PetscBool ignorezeroentries = a->ignorezeroentries; 5568 PetscBool roworiented = a->roworiented; 5569 5570 PetscFunctionBegin; 5571 MatCheckPreallocated(A,1); 5572 imax = a->imax; 5573 ai = a->i; 5574 ailen = a->ilen; 5575 aj = a->j; 5576 aa = a->a; 5577 5578 for (k=0; k<m; k++) { /* loop over added rows */ 5579 row = im[k]; 5580 if (row < 0) continue; 5581 if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large"); 5582 rp = aj + ai[row]; ap = aa + ai[row]; 5583 rmax = imax[row]; nrow = ailen[row]; 5584 low = 0; 5585 high = nrow; 5586 for (l=0; l<n; l++) { /* loop over added columns */ 5587 if (in[l] < 0) continue; 5588 if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large"); 5589 col = in[l]; 5590 if (roworiented) value = v[l + k*n]; 5591 else value = v[k + l*m]; 5592 5593 if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 5594 5595 if (col <= lastcol) low = 0; 5596 else high = nrow; 5597 lastcol = col; 5598 while (high-low > 5) { 5599 t = (low+high)/2; 5600 if (rp[t] > col) high = t; 5601 else low = t; 5602 } 5603 for (i=low; i<high; i++) { 5604 if (rp[i] > col) break; 5605 if (rp[i] == col) { 5606 if (is == ADD_VALUES) ap[i] += value; 5607 else ap[i] = value; 5608 goto noinsert; 5609 } 5610 } 5611 if (value == 0.0 && ignorezeroentries) goto noinsert; 5612 if (nonew == 1) goto noinsert; 5613 if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix"); 5614 MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar); 5615 N = nrow++ - 1; a->nz++; high++; 5616 /* shift up all the later entries in this row */ 5617 for (ii=N; ii>=i; ii--) { 5618 rp[ii+1] = rp[ii]; 5619 ap[ii+1] = ap[ii]; 5620 } 5621 rp[i] = col; 5622 ap[i] = value; 5623 A->nonzerostate++; 5624 noinsert:; 5625 low = i + 1; 5626 } 5627 ailen[row] = nrow; 5628 } 5629 PetscFunctionReturnVoid(); 5630 } 5631 /* Undefining these here since they were redefined from their original definition above! No 5632 * other PETSc functions should be defined past this point, as it is impossible to recover the 5633 * original definitions */ 5634 #undef CHKERRQ 5635 #undef SETERRQ 5636