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