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