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