1 2 /* 3 Defines the basic matrix operations for the AIJ (compressed row) 4 matrix storage format. 5 */ 6 7 8 #include <../src/mat/impls/aij/seq/aij.h> /*I "petscmat.h" I*/ 9 #include <petscblaslapack.h> 10 #include <petscbt.h> 11 #include <../src/mat/blocktranspose.h> 12 13 #undef __FUNCT__ 14 #define __FUNCT__ "MatGetColumnNorms_SeqAIJ" 15 PetscErrorCode MatGetColumnNorms_SeqAIJ(Mat A,NormType type,PetscReal *norms) 16 { 17 PetscErrorCode ierr; 18 PetscInt i,m,n; 19 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 20 21 PetscFunctionBegin; 22 ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr); 23 ierr = PetscMemzero(norms,n*sizeof(PetscReal));CHKERRQ(ierr); 24 if (type == NORM_2) { 25 for (i=0; i<aij->i[m]; i++) { 26 norms[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]); 27 } 28 } else if (type == NORM_1) { 29 for (i=0; i<aij->i[m]; i++) { 30 norms[aij->j[i]] += PetscAbsScalar(aij->a[i]); 31 } 32 } else if (type == NORM_INFINITY) { 33 for (i=0; i<aij->i[m]; i++) { 34 norms[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),norms[aij->j[i]]); 35 } 36 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown NormType"); 37 38 if (type == NORM_2) { 39 for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]); 40 } 41 PetscFunctionReturn(0); 42 } 43 44 #undef __FUNCT__ 45 #define __FUNCT__ "MatFindZeroDiagonals_SeqAIJ" 46 PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows) 47 { 48 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 49 const MatScalar *aa = a->a; 50 PetscInt i,m=A->rmap->n,cnt = 0; 51 const PetscInt *jj = a->j,*diag; 52 PetscInt *rows; 53 PetscErrorCode ierr; 54 55 PetscFunctionBegin; 56 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 57 diag = a->diag; 58 for (i=0; i<m; i++) { 59 if ((jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) { 60 cnt++; 61 } 62 } 63 ierr = PetscMalloc(cnt*sizeof(PetscInt),&rows);CHKERRQ(ierr); 64 cnt = 0; 65 for (i=0; i<m; i++) { 66 if ((jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) { 67 rows[cnt++] = i; 68 } 69 } 70 ierr = ISCreateGeneral(((PetscObject)A)->comm,cnt,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr); 71 PetscFunctionReturn(0); 72 } 73 74 #undef __FUNCT__ 75 #define __FUNCT__ "MatFindNonzeroRows_SeqAIJ" 76 PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows) 77 { 78 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 79 const MatScalar *aa; 80 PetscInt m=A->rmap->n,cnt = 0; 81 const PetscInt *ii; 82 PetscInt n,i,j,*rows; 83 PetscErrorCode ierr; 84 85 PetscFunctionBegin; 86 *keptrows = 0; 87 ii = a->i; 88 for (i=0; i<m; i++) { 89 n = ii[i+1] - ii[i]; 90 if (!n) { 91 cnt++; 92 goto ok1; 93 } 94 aa = a->a + ii[i]; 95 for (j=0; j<n; j++) { 96 if (aa[j] != 0.0) goto ok1; 97 } 98 cnt++; 99 ok1:; 100 } 101 if (!cnt) PetscFunctionReturn(0); 102 ierr = PetscMalloc((A->rmap->n-cnt)*sizeof(PetscInt),&rows);CHKERRQ(ierr); 103 cnt = 0; 104 for (i=0; i<m; i++) { 105 n = ii[i+1] - ii[i]; 106 if (!n) continue; 107 aa = a->a + ii[i]; 108 for (j=0; j<n; j++) { 109 if (aa[j] != 0.0) { 110 rows[cnt++] = i; 111 break; 112 } 113 } 114 } 115 ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr); 116 PetscFunctionReturn(0); 117 } 118 119 #undef __FUNCT__ 120 #define __FUNCT__ "MatDiagonalSet_SeqAIJ" 121 PetscErrorCode MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is) 122 { 123 PetscErrorCode ierr; 124 Mat_SeqAIJ *aij = (Mat_SeqAIJ*) Y->data; 125 PetscInt i,*diag, m = Y->rmap->n; 126 MatScalar *aa = aij->a; 127 PetscScalar *v; 128 PetscBool missing; 129 130 PetscFunctionBegin; 131 if (Y->assembled) { 132 ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,PETSC_NULL);CHKERRQ(ierr); 133 if (!missing) { 134 diag = aij->diag; 135 ierr = VecGetArray(D,&v);CHKERRQ(ierr); 136 if (is == INSERT_VALUES) { 137 for (i=0; i<m; i++) { 138 aa[diag[i]] = v[i]; 139 } 140 } else { 141 for (i=0; i<m; i++) { 142 aa[diag[i]] += v[i]; 143 } 144 } 145 ierr = VecRestoreArray(D,&v);CHKERRQ(ierr); 146 PetscFunctionReturn(0); 147 } 148 aij->idiagvalid = PETSC_FALSE; 149 aij->ibdiagvalid = PETSC_FALSE; 150 } 151 ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr); 152 PetscFunctionReturn(0); 153 } 154 155 #undef __FUNCT__ 156 #define __FUNCT__ "MatGetRowIJ_SeqAIJ" 157 PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,PetscInt *ia[],PetscInt *ja[],PetscBool *done) 158 { 159 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 160 PetscErrorCode ierr; 161 PetscInt i,ishift; 162 163 PetscFunctionBegin; 164 *m = A->rmap->n; 165 if (!ia) PetscFunctionReturn(0); 166 ishift = 0; 167 if (symmetric && !A->structurally_symmetric) { 168 ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,ishift,oshift,ia,ja);CHKERRQ(ierr); 169 } else if (oshift == 1) { 170 PetscInt nz = a->i[A->rmap->n]; 171 /* malloc space and add 1 to i and j indices */ 172 ierr = PetscMalloc((A->rmap->n+1)*sizeof(PetscInt),ia);CHKERRQ(ierr); 173 for (i=0; i<A->rmap->n+1; i++) (*ia)[i] = a->i[i] + 1; 174 if (ja) { 175 ierr = PetscMalloc((nz+1)*sizeof(PetscInt),ja);CHKERRQ(ierr); 176 for (i=0; i<nz; i++) (*ja)[i] = a->j[i] + 1; 177 } 178 } else { 179 *ia = a->i; 180 if (ja) *ja = a->j; 181 } 182 PetscFunctionReturn(0); 183 } 184 185 #undef __FUNCT__ 186 #define __FUNCT__ "MatRestoreRowIJ_SeqAIJ" 187 PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscBool *done) 188 { 189 PetscErrorCode ierr; 190 191 PetscFunctionBegin; 192 if (!ia) PetscFunctionReturn(0); 193 if ((symmetric && !A->structurally_symmetric) || oshift == 1) { 194 ierr = PetscFree(*ia);CHKERRQ(ierr); 195 if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);} 196 } 197 PetscFunctionReturn(0); 198 } 199 200 #undef __FUNCT__ 201 #define __FUNCT__ "MatGetColumnIJ_SeqAIJ" 202 PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscBool *done) 203 { 204 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 205 PetscErrorCode ierr; 206 PetscInt i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n; 207 PetscInt nz = a->i[m],row,*jj,mr,col; 208 209 PetscFunctionBegin; 210 *nn = n; 211 if (!ia) PetscFunctionReturn(0); 212 if (symmetric) { 213 ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,0,oshift,ia,ja);CHKERRQ(ierr); 214 } else { 215 ierr = PetscMalloc((n+1)*sizeof(PetscInt),&collengths);CHKERRQ(ierr); 216 ierr = PetscMemzero(collengths,n*sizeof(PetscInt));CHKERRQ(ierr); 217 ierr = PetscMalloc((n+1)*sizeof(PetscInt),&cia);CHKERRQ(ierr); 218 ierr = PetscMalloc((nz+1)*sizeof(PetscInt),&cja);CHKERRQ(ierr); 219 jj = a->j; 220 for (i=0; i<nz; i++) { 221 collengths[jj[i]]++; 222 } 223 cia[0] = oshift; 224 for (i=0; i<n; i++) { 225 cia[i+1] = cia[i] + collengths[i]; 226 } 227 ierr = PetscMemzero(collengths,n*sizeof(PetscInt));CHKERRQ(ierr); 228 jj = a->j; 229 for (row=0; row<m; row++) { 230 mr = a->i[row+1] - a->i[row]; 231 for (i=0; i<mr; i++) { 232 col = *jj++; 233 cja[cia[col] + collengths[col]++ - oshift] = row + oshift; 234 } 235 } 236 ierr = PetscFree(collengths);CHKERRQ(ierr); 237 *ia = cia; *ja = cja; 238 } 239 PetscFunctionReturn(0); 240 } 241 242 #undef __FUNCT__ 243 #define __FUNCT__ "MatRestoreColumnIJ_SeqAIJ" 244 PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscBool *done) 245 { 246 PetscErrorCode ierr; 247 248 PetscFunctionBegin; 249 if (!ia) PetscFunctionReturn(0); 250 251 ierr = PetscFree(*ia);CHKERRQ(ierr); 252 ierr = PetscFree(*ja);CHKERRQ(ierr); 253 254 PetscFunctionReturn(0); 255 } 256 257 #undef __FUNCT__ 258 #define __FUNCT__ "MatSetValuesRow_SeqAIJ" 259 PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[]) 260 { 261 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 262 PetscInt *ai = a->i; 263 PetscErrorCode ierr; 264 265 PetscFunctionBegin; 266 ierr = PetscMemcpy(a->a+ai[row],v,(ai[row+1]-ai[row])*sizeof(PetscScalar));CHKERRQ(ierr); 267 PetscFunctionReturn(0); 268 } 269 270 #undef __FUNCT__ 271 #define __FUNCT__ "MatSetValues_SeqAIJ" 272 PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is) 273 { 274 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 275 PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N; 276 PetscInt *imax = a->imax,*ai = a->i,*ailen = a->ilen; 277 PetscErrorCode ierr; 278 PetscInt *aj = a->j,nonew = a->nonew,lastcol = -1; 279 MatScalar *ap,value,*aa = a->a; 280 PetscBool ignorezeroentries = a->ignorezeroentries; 281 PetscBool roworiented = a->roworiented; 282 283 PetscFunctionBegin; 284 if (v) PetscValidScalarPointer(v,6); 285 for (k=0; k<m; k++) { /* loop over added rows */ 286 row = im[k]; 287 if (row < 0) continue; 288 #if defined(PETSC_USE_DEBUG) 289 if (row >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1); 290 #endif 291 rp = aj + ai[row]; ap = aa + ai[row]; 292 rmax = imax[row]; nrow = ailen[row]; 293 low = 0; 294 high = nrow; 295 for (l=0; l<n; l++) { /* loop over added columns */ 296 if (in[l] < 0) continue; 297 #if defined(PETSC_USE_DEBUG) 298 if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1); 299 #endif 300 col = in[l]; 301 if (v) { 302 if (roworiented) { 303 value = v[l + k*n]; 304 } else { 305 value = v[k + l*m]; 306 } 307 } else { 308 value = 0.; 309 } 310 if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 311 312 if (col <= lastcol) low = 0; else high = nrow; 313 lastcol = col; 314 while (high-low > 5) { 315 t = (low+high)/2; 316 if (rp[t] > col) high = t; 317 else low = t; 318 } 319 for (i=low; i<high; i++) { 320 if (rp[i] > col) break; 321 if (rp[i] == col) { 322 if (is == ADD_VALUES) ap[i] += value; 323 else ap[i] = value; 324 low = i + 1; 325 goto noinsert; 326 } 327 } 328 if (value == 0.0 && ignorezeroentries) goto noinsert; 329 if (nonew == 1) goto noinsert; 330 if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col); 331 MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar); 332 N = nrow++ - 1; a->nz++; high++; 333 /* shift up all the later entries in this row */ 334 for (ii=N; ii>=i; ii--) { 335 rp[ii+1] = rp[ii]; 336 ap[ii+1] = ap[ii]; 337 } 338 rp[i] = col; 339 ap[i] = value; 340 low = i + 1; 341 noinsert:; 342 } 343 ailen[row] = nrow; 344 } 345 A->same_nonzero = PETSC_FALSE; 346 PetscFunctionReturn(0); 347 } 348 349 350 #undef __FUNCT__ 351 #define __FUNCT__ "MatGetValues_SeqAIJ" 352 PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[]) 353 { 354 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 355 PetscInt *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j; 356 PetscInt *ai = a->i,*ailen = a->ilen; 357 MatScalar *ap,*aa = a->a; 358 359 PetscFunctionBegin; 360 for (k=0; k<m; k++) { /* loop over rows */ 361 row = im[k]; 362 if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */ 363 if (row >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1); 364 rp = aj + ai[row]; ap = aa + ai[row]; 365 nrow = ailen[row]; 366 for (l=0; l<n; l++) { /* loop over columns */ 367 if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */ 368 if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1); 369 col = in[l] ; 370 high = nrow; low = 0; /* assume unsorted */ 371 while (high-low > 5) { 372 t = (low+high)/2; 373 if (rp[t] > col) high = t; 374 else low = t; 375 } 376 for (i=low; i<high; i++) { 377 if (rp[i] > col) break; 378 if (rp[i] == col) { 379 *v++ = ap[i]; 380 goto finished; 381 } 382 } 383 *v++ = 0.0; 384 finished:; 385 } 386 } 387 PetscFunctionReturn(0); 388 } 389 390 391 #undef __FUNCT__ 392 #define __FUNCT__ "MatView_SeqAIJ_Binary" 393 PetscErrorCode MatView_SeqAIJ_Binary(Mat A,PetscViewer viewer) 394 { 395 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 396 PetscErrorCode ierr; 397 PetscInt i,*col_lens; 398 int fd; 399 400 PetscFunctionBegin; 401 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 402 ierr = PetscMalloc((4+A->rmap->n)*sizeof(PetscInt),&col_lens);CHKERRQ(ierr); 403 col_lens[0] = MAT_FILE_CLASSID; 404 col_lens[1] = A->rmap->n; 405 col_lens[2] = A->cmap->n; 406 col_lens[3] = a->nz; 407 408 /* store lengths of each row and write (including header) to file */ 409 for (i=0; i<A->rmap->n; i++) { 410 col_lens[4+i] = a->i[i+1] - a->i[i]; 411 } 412 ierr = PetscBinaryWrite(fd,col_lens,4+A->rmap->n,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 413 ierr = PetscFree(col_lens);CHKERRQ(ierr); 414 415 /* store column indices (zero start index) */ 416 ierr = PetscBinaryWrite(fd,a->j,a->nz,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 417 418 /* store nonzero values */ 419 ierr = PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr); 420 PetscFunctionReturn(0); 421 } 422 423 extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer); 424 425 #undef __FUNCT__ 426 #define __FUNCT__ "MatView_SeqAIJ_ASCII" 427 PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer) 428 { 429 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 430 PetscErrorCode ierr; 431 PetscInt i,j,m = A->rmap->n,shift=0; 432 const char *name; 433 PetscViewerFormat format; 434 435 PetscFunctionBegin; 436 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 437 if (format == PETSC_VIEWER_ASCII_MATLAB) { 438 PetscInt nofinalvalue = 0; 439 if ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-!shift)) { 440 nofinalvalue = 1; 441 } 442 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 443 ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr); 444 ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr); 445 ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr); 446 ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr); 447 448 for (i=0; i<m; i++) { 449 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 450 #if defined(PETSC_USE_COMPLEX) 451 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %18.16e + %18.16ei \n",i+1,a->j[j]+!shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 452 #else 453 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %18.16e\n",i+1,a->j[j]+!shift,a->a[j]);CHKERRQ(ierr); 454 #endif 455 } 456 } 457 if (nofinalvalue) { 458 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr); 459 } 460 ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr); 461 ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr); 462 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 463 } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) { 464 PetscFunctionReturn(0); 465 } else if (format == PETSC_VIEWER_ASCII_COMMON) { 466 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 467 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");CHKERRQ(ierr); 468 for (i=0; i<m; i++) { 469 ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr); 470 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 471 #if defined(PETSC_USE_COMPLEX) 472 if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) { 473 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 474 } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) { 475 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 476 } else if (PetscRealPart(a->a[j]) != 0.0) { 477 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr); 478 } 479 #else 480 if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);} 481 #endif 482 } 483 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 484 } 485 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 486 } else if (format == PETSC_VIEWER_ASCII_SYMMODU) { 487 PetscInt nzd=0,fshift=1,*sptr; 488 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 489 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");CHKERRQ(ierr); 490 ierr = PetscMalloc((m+1)*sizeof(PetscInt),&sptr);CHKERRQ(ierr); 491 for (i=0; i<m; i++) { 492 sptr[i] = nzd+1; 493 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 494 if (a->j[j] >= i) { 495 #if defined(PETSC_USE_COMPLEX) 496 if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++; 497 #else 498 if (a->a[j] != 0.0) nzd++; 499 #endif 500 } 501 } 502 } 503 sptr[m] = nzd+1; 504 ierr = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr); 505 for (i=0; i<m+1; i+=6) { 506 if (i+4<m) {ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4],sptr[i+5]);CHKERRQ(ierr);} 507 else if (i+3<m) {ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4]);CHKERRQ(ierr);} 508 else if (i+2<m) {ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);} 509 else if (i+1<m) {ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);} 510 else if (i<m) {ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);} 511 else {ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);} 512 } 513 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 514 ierr = PetscFree(sptr);CHKERRQ(ierr); 515 for (i=0; i<m; i++) { 516 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 517 if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);} 518 } 519 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 520 } 521 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 522 for (i=0; i<m; i++) { 523 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 524 if (a->j[j] >= i) { 525 #if defined(PETSC_USE_COMPLEX) 526 if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) { 527 ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 528 } 529 #else 530 if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",a->a[j]);CHKERRQ(ierr);} 531 #endif 532 } 533 } 534 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 535 } 536 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 537 } else if (format == PETSC_VIEWER_ASCII_DENSE) { 538 PetscInt cnt = 0,jcnt; 539 PetscScalar value; 540 541 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 542 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");CHKERRQ(ierr); 543 for (i=0; i<m; i++) { 544 jcnt = 0; 545 for (j=0; j<A->cmap->n; j++) { 546 if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) { 547 value = a->a[cnt++]; 548 jcnt++; 549 } else { 550 value = 0.0; 551 } 552 #if defined(PETSC_USE_COMPLEX) 553 ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",PetscRealPart(value),PetscImaginaryPart(value));CHKERRQ(ierr); 554 #else 555 ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",value);CHKERRQ(ierr); 556 #endif 557 } 558 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 559 } 560 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 561 } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) { 562 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 563 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");CHKERRQ(ierr); 564 #if defined(PETSC_USE_COMPLEX) 565 ierr = PetscViewerASCIIPrintf(viewer,"%%matrix complex general\n");CHKERRQ(ierr); 566 #else 567 ierr = PetscViewerASCIIPrintf(viewer,"%%matrix real general\n");CHKERRQ(ierr); 568 #endif 569 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr); 570 for (i=0; i<m; i++) { 571 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 572 #if defined(PETSC_USE_COMPLEX) 573 if (PetscImaginaryPart(a->a[j]) > 0.0) { 574 ierr = PetscViewerASCIIPrintf(viewer,"%D %D, %G %G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 575 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 576 ierr = PetscViewerASCIIPrintf(viewer,"%D %D, %G -%G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 577 } else { 578 ierr = PetscViewerASCIIPrintf(viewer,"%D %D, %G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr); 579 } 580 #else 581 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %G\n", i+shift, a->j[j]+shift, a->a[j]);CHKERRQ(ierr); 582 #endif 583 } 584 } 585 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 586 } else { 587 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 588 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");CHKERRQ(ierr); 589 if (A->factortype){ 590 for (i=0; i<m; i++) { 591 ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr); 592 /* L part */ 593 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 594 #if defined(PETSC_USE_COMPLEX) 595 if (PetscImaginaryPart(a->a[j]) > 0.0) { 596 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 597 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 598 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 599 } else { 600 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr); 601 } 602 #else 603 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr); 604 #endif 605 } 606 /* diagonal */ 607 j = a->diag[i]; 608 #if defined(PETSC_USE_COMPLEX) 609 if (PetscImaginaryPart(a->a[j]) > 0.0) { 610 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(1.0/a->a[j]),PetscImaginaryPart(1.0/a->a[j]));CHKERRQ(ierr); 611 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 612 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(1.0/a->a[j]),-PetscImaginaryPart(1.0/a->a[j]));CHKERRQ(ierr); 613 } else { 614 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(1.0/a->a[j]));CHKERRQ(ierr); 615 } 616 #else 617 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,1.0/a->a[j]);CHKERRQ(ierr); 618 #endif 619 620 /* U part */ 621 for (j=a->diag[i+1]+1+shift; j<a->diag[i]+shift; j++) { 622 #if defined(PETSC_USE_COMPLEX) 623 if (PetscImaginaryPart(a->a[j]) > 0.0) { 624 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 625 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 626 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 627 } else { 628 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr); 629 } 630 #else 631 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr); 632 #endif 633 } 634 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 635 } 636 } else { 637 for (i=0; i<m; i++) { 638 ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr); 639 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 640 #if defined(PETSC_USE_COMPLEX) 641 if (PetscImaginaryPart(a->a[j]) > 0.0) { 642 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 643 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 644 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 645 } else { 646 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr); 647 } 648 #else 649 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr); 650 #endif 651 } 652 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 653 } 654 } 655 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 656 } 657 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 658 PetscFunctionReturn(0); 659 } 660 661 #undef __FUNCT__ 662 #define __FUNCT__ "MatView_SeqAIJ_Draw_Zoom" 663 PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa) 664 { 665 Mat A = (Mat) Aa; 666 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 667 PetscErrorCode ierr; 668 PetscInt i,j,m = A->rmap->n,color; 669 PetscReal xl,yl,xr,yr,x_l,x_r,y_l,y_r,maxv = 0.0; 670 PetscViewer viewer; 671 PetscViewerFormat format; 672 673 PetscFunctionBegin; 674 ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr); 675 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 676 677 ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 678 /* loop over matrix elements drawing boxes */ 679 680 if (format != PETSC_VIEWER_DRAW_CONTOUR) { 681 /* Blue for negative, Cyan for zero and Red for positive */ 682 color = PETSC_DRAW_BLUE; 683 for (i=0; i<m; i++) { 684 y_l = m - i - 1.0; y_r = y_l + 1.0; 685 for (j=a->i[i]; j<a->i[i+1]; j++) { 686 x_l = a->j[j] ; x_r = x_l + 1.0; 687 #if defined(PETSC_USE_COMPLEX) 688 if (PetscRealPart(a->a[j]) >= 0.) continue; 689 #else 690 if (a->a[j] >= 0.) continue; 691 #endif 692 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 693 } 694 } 695 color = PETSC_DRAW_CYAN; 696 for (i=0; i<m; i++) { 697 y_l = m - i - 1.0; y_r = y_l + 1.0; 698 for (j=a->i[i]; j<a->i[i+1]; j++) { 699 x_l = a->j[j]; x_r = x_l + 1.0; 700 if (a->a[j] != 0.) continue; 701 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 702 } 703 } 704 color = PETSC_DRAW_RED; 705 for (i=0; i<m; i++) { 706 y_l = m - i - 1.0; y_r = y_l + 1.0; 707 for (j=a->i[i]; j<a->i[i+1]; j++) { 708 x_l = a->j[j]; x_r = x_l + 1.0; 709 #if defined(PETSC_USE_COMPLEX) 710 if (PetscRealPart(a->a[j]) <= 0.) continue; 711 #else 712 if (a->a[j] <= 0.) continue; 713 #endif 714 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 715 } 716 } 717 } else { 718 /* use contour shading to indicate magnitude of values */ 719 /* first determine max of all nonzero values */ 720 PetscInt nz = a->nz,count; 721 PetscDraw popup; 722 PetscReal scale; 723 724 for (i=0; i<nz; i++) { 725 if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]); 726 } 727 scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/maxv; 728 ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr); 729 if (popup) {ierr = PetscDrawScalePopup(popup,0.0,maxv);CHKERRQ(ierr);} 730 count = 0; 731 for (i=0; i<m; i++) { 732 y_l = m - i - 1.0; y_r = y_l + 1.0; 733 for (j=a->i[i]; j<a->i[i+1]; j++) { 734 x_l = a->j[j]; x_r = x_l + 1.0; 735 color = PETSC_DRAW_BASIC_COLORS + (PetscInt)(scale*PetscAbsScalar(a->a[count])); 736 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 737 count++; 738 } 739 } 740 } 741 PetscFunctionReturn(0); 742 } 743 744 #undef __FUNCT__ 745 #define __FUNCT__ "MatView_SeqAIJ_Draw" 746 PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer) 747 { 748 PetscErrorCode ierr; 749 PetscDraw draw; 750 PetscReal xr,yr,xl,yl,h,w; 751 PetscBool isnull; 752 753 PetscFunctionBegin; 754 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 755 ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); 756 if (isnull) PetscFunctionReturn(0); 757 758 ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr); 759 xr = A->cmap->n; yr = A->rmap->n; h = yr/10.0; w = xr/10.0; 760 xr += w; yr += h; xl = -w; yl = -h; 761 ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr); 762 ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr); 763 ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr); 764 PetscFunctionReturn(0); 765 } 766 767 #undef __FUNCT__ 768 #define __FUNCT__ "MatView_SeqAIJ" 769 PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer) 770 { 771 PetscErrorCode ierr; 772 PetscBool iascii,isbinary,isdraw; 773 774 PetscFunctionBegin; 775 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 776 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 777 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 778 if (iascii) { 779 ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr); 780 } else if (isbinary) { 781 ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr); 782 } else if (isdraw) { 783 ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr); 784 } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported by SeqAIJ matrices",((PetscObject)viewer)->type_name); 785 ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr); 786 PetscFunctionReturn(0); 787 } 788 789 #undef __FUNCT__ 790 #define __FUNCT__ "MatAssemblyEnd_SeqAIJ" 791 PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode) 792 { 793 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 794 PetscErrorCode ierr; 795 PetscInt fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax; 796 PetscInt m = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0; 797 MatScalar *aa = a->a,*ap; 798 PetscReal ratio=0.6; 799 800 PetscFunctionBegin; 801 if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 802 803 if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 804 for (i=1; i<m; i++) { 805 /* move each row back by the amount of empty slots (fshift) before it*/ 806 fshift += imax[i-1] - ailen[i-1]; 807 rmax = PetscMax(rmax,ailen[i]); 808 if (fshift) { 809 ip = aj + ai[i] ; 810 ap = aa + ai[i] ; 811 N = ailen[i]; 812 for (j=0; j<N; j++) { 813 ip[j-fshift] = ip[j]; 814 ap[j-fshift] = ap[j]; 815 } 816 } 817 ai[i] = ai[i-1] + ailen[i-1]; 818 } 819 if (m) { 820 fshift += imax[m-1] - ailen[m-1]; 821 ai[m] = ai[m-1] + ailen[m-1]; 822 } 823 /* reset ilen and imax for each row */ 824 for (i=0; i<m; i++) { 825 ailen[i] = imax[i] = ai[i+1] - ai[i]; 826 } 827 a->nz = ai[m]; 828 if (fshift && a->nounused == -1) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Unused space detected in matrix: %D X %D, %D unneeded", m, A->cmap->n, fshift); 829 830 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 831 ierr = PetscInfo4(A,"Matrix size: %D X %D; storage space: %D unneeded,%D used\n",m,A->cmap->n,fshift,a->nz);CHKERRQ(ierr); 832 ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr); 833 ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr); 834 A->info.mallocs += a->reallocs; 835 a->reallocs = 0; 836 A->info.nz_unneeded = (double)fshift; 837 a->rmax = rmax; 838 839 ierr = MatCheckCompressedRow(A,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr); 840 A->same_nonzero = PETSC_TRUE; 841 842 ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr); 843 844 a->idiagvalid = PETSC_FALSE; 845 a->ibdiagvalid = PETSC_FALSE; 846 PetscFunctionReturn(0); 847 } 848 849 #undef __FUNCT__ 850 #define __FUNCT__ "MatRealPart_SeqAIJ" 851 PetscErrorCode MatRealPart_SeqAIJ(Mat A) 852 { 853 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 854 PetscInt i,nz = a->nz; 855 MatScalar *aa = a->a; 856 857 PetscFunctionBegin; 858 for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]); 859 a->idiagvalid = PETSC_FALSE; 860 a->ibdiagvalid = PETSC_FALSE; 861 PetscFunctionReturn(0); 862 } 863 864 #undef __FUNCT__ 865 #define __FUNCT__ "MatImaginaryPart_SeqAIJ" 866 PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A) 867 { 868 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 869 PetscInt i,nz = a->nz; 870 MatScalar *aa = a->a; 871 872 PetscFunctionBegin; 873 for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]); 874 a->idiagvalid = PETSC_FALSE; 875 a->ibdiagvalid = PETSC_FALSE; 876 PetscFunctionReturn(0); 877 } 878 879 #undef __FUNCT__ 880 #define __FUNCT__ "MatZeroEntries_SeqAIJ" 881 PetscErrorCode MatZeroEntries_SeqAIJ(Mat A) 882 { 883 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 884 PetscErrorCode ierr; 885 886 PetscFunctionBegin; 887 ierr = PetscMemzero(a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));CHKERRQ(ierr); 888 a->idiagvalid = PETSC_FALSE; 889 a->ibdiagvalid = PETSC_FALSE; 890 PetscFunctionReturn(0); 891 } 892 893 #undef __FUNCT__ 894 #define __FUNCT__ "MatDestroy_SeqAIJ" 895 PetscErrorCode MatDestroy_SeqAIJ(Mat A) 896 { 897 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 898 PetscErrorCode ierr; 899 900 PetscFunctionBegin; 901 #if defined(PETSC_USE_LOG) 902 PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz); 903 #endif 904 ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr); 905 ierr = ISDestroy(&a->row);CHKERRQ(ierr); 906 ierr = ISDestroy(&a->col);CHKERRQ(ierr); 907 ierr = PetscFree(a->diag);CHKERRQ(ierr); 908 ierr = PetscFree(a->ibdiag);CHKERRQ(ierr); 909 ierr = PetscFree2(a->imax,a->ilen);CHKERRQ(ierr); 910 ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr); 911 ierr = PetscFree(a->solve_work);CHKERRQ(ierr); 912 ierr = ISDestroy(&a->icol);CHKERRQ(ierr); 913 ierr = PetscFree(a->saved_values);CHKERRQ(ierr); 914 ierr = ISColoringDestroy(&a->coloring);CHKERRQ(ierr); 915 ierr = PetscFree(a->xtoy);CHKERRQ(ierr); 916 ierr = MatDestroy(&a->XtoY);CHKERRQ(ierr); 917 ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr); 918 919 ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr); 920 ierr = PetscFree(A->data);CHKERRQ(ierr); 921 922 ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 923 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetColumnIndices_C","",PETSC_NULL);CHKERRQ(ierr); 924 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatStoreValues_C","",PETSC_NULL);CHKERRQ(ierr); 925 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatRetrieveValues_C","",PETSC_NULL);CHKERRQ(ierr); 926 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqsbaij_C","",PETSC_NULL);CHKERRQ(ierr); 927 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqbaij_C","",PETSC_NULL);CHKERRQ(ierr); 928 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqaijperm_C","",PETSC_NULL);CHKERRQ(ierr); 929 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatIsTranspose_C","",PETSC_NULL);CHKERRQ(ierr); 930 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocation_C","",PETSC_NULL);CHKERRQ(ierr); 931 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C","",PETSC_NULL);CHKERRQ(ierr); 932 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatReorderForNonzeroDiagonal_C","",PETSC_NULL);CHKERRQ(ierr); 933 PetscFunctionReturn(0); 934 } 935 936 #undef __FUNCT__ 937 #define __FUNCT__ "MatSetOption_SeqAIJ" 938 PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg) 939 { 940 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 941 PetscErrorCode ierr; 942 943 PetscFunctionBegin; 944 switch (op) { 945 case MAT_ROW_ORIENTED: 946 a->roworiented = flg; 947 break; 948 case MAT_KEEP_NONZERO_PATTERN: 949 a->keepnonzeropattern = flg; 950 break; 951 case MAT_NEW_NONZERO_LOCATIONS: 952 a->nonew = (flg ? 0 : 1); 953 break; 954 case MAT_NEW_NONZERO_LOCATION_ERR: 955 a->nonew = (flg ? -1 : 0); 956 break; 957 case MAT_NEW_NONZERO_ALLOCATION_ERR: 958 a->nonew = (flg ? -2 : 0); 959 break; 960 case MAT_UNUSED_NONZERO_LOCATION_ERR: 961 a->nounused = (flg ? -1 : 0); 962 break; 963 case MAT_IGNORE_ZERO_ENTRIES: 964 a->ignorezeroentries = flg; 965 break; 966 case MAT_CHECK_COMPRESSED_ROW: 967 a->compressedrow.check = flg; 968 break; 969 case MAT_SPD: 970 A->spd_set = PETSC_TRUE; 971 A->spd = flg; 972 if (flg) { 973 A->symmetric = PETSC_TRUE; 974 A->structurally_symmetric = PETSC_TRUE; 975 A->symmetric_set = PETSC_TRUE; 976 A->structurally_symmetric_set = PETSC_TRUE; 977 } 978 break; 979 case MAT_SYMMETRIC: 980 case MAT_STRUCTURALLY_SYMMETRIC: 981 case MAT_HERMITIAN: 982 case MAT_SYMMETRY_ETERNAL: 983 case MAT_NEW_DIAGONALS: 984 case MAT_IGNORE_OFF_PROC_ENTRIES: 985 case MAT_USE_HASH_TABLE: 986 ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr); 987 break; 988 case MAT_USE_INODES: 989 /* Not an error because MatSetOption_SeqAIJ_Inode handles this one */ 990 break; 991 default: 992 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op); 993 } 994 ierr = MatSetOption_SeqAIJ_Inode(A,op,flg);CHKERRQ(ierr); 995 PetscFunctionReturn(0); 996 } 997 998 #undef __FUNCT__ 999 #define __FUNCT__ "MatGetDiagonal_SeqAIJ" 1000 PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v) 1001 { 1002 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1003 PetscErrorCode ierr; 1004 PetscInt i,j,n,*ai=a->i,*aj=a->j,nz; 1005 PetscScalar *aa=a->a,*x,zero=0.0; 1006 1007 PetscFunctionBegin; 1008 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 1009 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 1010 1011 if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU){ 1012 PetscInt *diag=a->diag; 1013 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 1014 for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]]; 1015 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 1016 PetscFunctionReturn(0); 1017 } 1018 1019 ierr = VecSet(v,zero);CHKERRQ(ierr); 1020 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 1021 for (i=0; i<n; i++) { 1022 nz = ai[i+1] - ai[i]; 1023 if (!nz) x[i] = 0.0; 1024 for (j=ai[i]; j<ai[i+1]; j++){ 1025 if (aj[j] == i) { 1026 x[i] = aa[j]; 1027 break; 1028 } 1029 } 1030 } 1031 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 1032 PetscFunctionReturn(0); 1033 } 1034 1035 #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 1036 #undef __FUNCT__ 1037 #define __FUNCT__ "MatMultTransposeAdd_SeqAIJ" 1038 PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy) 1039 { 1040 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1041 PetscScalar *x,*y; 1042 PetscErrorCode ierr; 1043 PetscInt m = A->rmap->n; 1044 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 1045 MatScalar *v; 1046 PetscScalar alpha; 1047 PetscInt n,i,j,*idx,*ii,*ridx=PETSC_NULL; 1048 Mat_CompressedRow cprow = a->compressedrow; 1049 PetscBool usecprow = cprow.use; 1050 #endif 1051 1052 PetscFunctionBegin; 1053 if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);} 1054 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 1055 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 1056 1057 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 1058 fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y); 1059 #else 1060 if (usecprow){ 1061 m = cprow.nrows; 1062 ii = cprow.i; 1063 ridx = cprow.rindex; 1064 } else { 1065 ii = a->i; 1066 } 1067 for (i=0; i<m; i++) { 1068 idx = a->j + ii[i] ; 1069 v = a->a + ii[i] ; 1070 n = ii[i+1] - ii[i]; 1071 if (usecprow){ 1072 alpha = x[ridx[i]]; 1073 } else { 1074 alpha = x[i]; 1075 } 1076 for (j=0; j<n; j++) y[idx[j]] += alpha*v[j]; 1077 } 1078 #endif 1079 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1080 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1081 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 1082 PetscFunctionReturn(0); 1083 } 1084 1085 #undef __FUNCT__ 1086 #define __FUNCT__ "MatMultTranspose_SeqAIJ" 1087 PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy) 1088 { 1089 PetscErrorCode ierr; 1090 1091 PetscFunctionBegin; 1092 ierr = VecSet(yy,0.0);CHKERRQ(ierr); 1093 ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr); 1094 PetscFunctionReturn(0); 1095 } 1096 1097 #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 1098 #undef __FUNCT__ 1099 #define __FUNCT__ "MatMult_SeqAIJ" 1100 PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy) 1101 { 1102 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1103 PetscScalar *y; 1104 const PetscScalar *x; 1105 const MatScalar *aa; 1106 PetscErrorCode ierr; 1107 PetscInt m=A->rmap->n; 1108 const PetscInt *aj,*ii,*ridx=PETSC_NULL; 1109 PetscInt n,i,nonzerorow=0; 1110 PetscScalar sum; 1111 PetscBool usecprow=a->compressedrow.use; 1112 1113 #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 1114 #pragma disjoint(*x,*y,*aa) 1115 #endif 1116 1117 PetscFunctionBegin; 1118 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 1119 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 1120 aj = a->j; 1121 aa = a->a; 1122 ii = a->i; 1123 if (usecprow){ /* use compressed row format */ 1124 m = a->compressedrow.nrows; 1125 ii = a->compressedrow.i; 1126 ridx = a->compressedrow.rindex; 1127 for (i=0; i<m; i++){ 1128 n = ii[i+1] - ii[i]; 1129 aj = a->j + ii[i]; 1130 aa = a->a + ii[i]; 1131 sum = 0.0; 1132 nonzerorow += (n>0); 1133 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1134 /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 1135 y[*ridx++] = sum; 1136 } 1137 } else { /* do not use compressed row format */ 1138 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ) 1139 fortranmultaij_(&m,x,ii,aj,aa,y); 1140 #else 1141 for (i=0; i<m; i++) { 1142 n = ii[i+1] - ii[i]; 1143 aj = a->j + ii[i]; 1144 aa = a->a + ii[i]; 1145 sum = 0.0; 1146 nonzerorow += (n>0); 1147 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1148 y[i] = sum; 1149 } 1150 #endif 1151 } 1152 ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr); 1153 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1154 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 1155 PetscFunctionReturn(0); 1156 } 1157 1158 #if defined(PETSC_HAVE_PTHREADCLASSES) 1159 1160 /* ******************* */ 1161 #if defined(PETSC_HAVE_PTHREADCLASSES) 1162 extern PetscBool PetscUseThreadPool; 1163 #if defined(PETSC_HAVE_CPU_SET_T) 1164 void* DoCoreAffinity(void); 1165 #endif 1166 1167 typedef struct { 1168 const MatScalar* matdata; 1169 const PetscScalar* vecdata; 1170 PetscScalar* vecout; 1171 const PetscInt* colindnz; 1172 const PetscInt* rownumnz; 1173 PetscInt numrows; 1174 const PetscInt* specidx; 1175 PetscInt nzr; 1176 } MatMult_KernelData; 1177 1178 void* MatMult_Kernel(void *arg) 1179 { 1180 if(PetscUseThreadPool==PETSC_FALSE) { 1181 #if defined(PETSC_HAVE_CPU_SET_T) 1182 DoCoreAffinity(); 1183 #endif 1184 } 1185 MatMult_KernelData *data = (MatMult_KernelData*)arg; 1186 PetscScalar sum; 1187 const MatScalar *aabase = data->matdata,*aa; 1188 const PetscScalar *x = data->vecdata; 1189 PetscScalar *y = data->vecout; 1190 const PetscInt *ajbase = data->colindnz,*aj; 1191 const PetscInt *ii = data->rownumnz; 1192 PetscInt m = data->numrows; 1193 const PetscInt *ridx = data->specidx; 1194 PetscInt i,n,nonzerorow = 0; 1195 1196 if(ridx!=NULL) { 1197 for (i=0; i<m; i++){ 1198 n = ii[i+1] - ii[i]; 1199 aj = ajbase + ii[i]; 1200 aa = aabase + ii[i]; 1201 sum = 0.0; 1202 if(n>0) { 1203 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1204 nonzerorow++; 1205 } 1206 y[*ridx++] = sum; 1207 } 1208 } 1209 else { 1210 PetscInt ibase = data->nzr; 1211 for (i=0; i<m; i++) { 1212 n = ii[i+1] - ii[i]; 1213 aj = ajbase + ii[i]; 1214 aa = aabase + ii[i]; 1215 sum = 0.0; 1216 if(n>0) { 1217 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1218 nonzerorow++; 1219 } 1220 y[i+ibase] = sum; 1221 } 1222 } 1223 data->nzr = nonzerorow; 1224 return NULL; 1225 } 1226 #endif 1227 1228 extern PetscMPIInt PetscMaxThreads; 1229 extern PetscErrorCode (*MainJob)(void* (*pFunc)(void*),void**,PetscInt); 1230 1231 #undef __FUNCT__ 1232 #define __FUNCT__ "MatMult_SeqAIJPThread" 1233 PetscErrorCode MatMult_SeqAIJPThread(Mat A,Vec xx,Vec yy) 1234 { 1235 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1236 PetscScalar *y; 1237 const PetscScalar *x; 1238 PetscErrorCode ierr; 1239 PetscInt m=A->rmap->n,nonzerorow=0; 1240 PetscBool usecprow=a->compressedrow.use; 1241 1242 #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 1243 #pragma disjoint(*x,*y,*aa) 1244 #endif 1245 1246 PetscFunctionBegin; 1247 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 1248 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 1249 1250 if(usecprow) { 1251 PetscInt NumPerThread,iindex; 1252 const MatScalar *aa = a->a; 1253 const PetscInt *aj = a->j,*ii = a->compressedrow.i,*ridx=a->compressedrow.rindex; 1254 PetscInt i,iStartVal,iEndVal,iStartIndex,iEndIndex; 1255 const PetscInt iNumThreads = PetscMaxThreads; /* this number could be different */ 1256 MatMult_KernelData* kerneldatap = (MatMult_KernelData*)malloc(iNumThreads*sizeof(MatMult_KernelData)); 1257 MatMult_KernelData** pdata = (MatMult_KernelData**)malloc(iNumThreads*sizeof(MatMult_KernelData*)); 1258 1259 m = a->compressedrow.nrows; 1260 NumPerThread = ii[m]/iNumThreads; 1261 iindex = 0; 1262 for(i=0; i<iNumThreads;i++) { 1263 iStartIndex = iindex; 1264 iStartVal = ii[iStartIndex]; 1265 iEndVal = iStartVal; 1266 /* determine number of rows to process */ 1267 while(iEndVal-iStartVal<NumPerThread) { 1268 iindex++; 1269 iEndVal = ii[iindex]; 1270 } 1271 /* determine whether to go back 1 */ 1272 if(iEndVal-iStartVal-NumPerThread>NumPerThread-(ii[iindex-1]-iStartVal)) { 1273 iindex--; 1274 iEndVal = ii[iindex]; 1275 } 1276 iEndIndex = iindex; 1277 kerneldatap[i].matdata = aa; 1278 kerneldatap[i].vecdata = x; 1279 kerneldatap[i].vecout = y; 1280 kerneldatap[i].colindnz = aj; 1281 kerneldatap[i].rownumnz = ii + iStartIndex; 1282 kerneldatap[i].numrows = iEndIndex - iStartIndex + 1; 1283 kerneldatap[i].specidx = ridx + iStartVal; 1284 kerneldatap[i].nzr = 0; 1285 pdata[i] = &kerneldatap[i]; 1286 iindex++; 1287 } 1288 ierr = MainJob(MatMult_Kernel,(void**)pdata,iNumThreads); 1289 /* collect results */ 1290 for(i=0; i<iNumThreads; i++) { 1291 nonzerorow += kerneldatap[i].nzr; 1292 } 1293 free(kerneldatap); 1294 free(pdata); 1295 } 1296 else { 1297 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ) 1298 fortranmultaij_(&m,x,a->i,a->j,a->a,y); 1299 #else 1300 PetscInt i,iindex; 1301 const MatScalar *aa = a->a; 1302 const PetscInt *aj = a->j,*ii = a->i; 1303 const PetscInt iNumThreads = PetscMaxThreads; /* this number could be different */ 1304 PetscInt Q = m/iNumThreads; 1305 PetscInt R = m-Q*iNumThreads; 1306 PetscBool S; 1307 1308 MatMult_KernelData* kerneldatap = (MatMult_KernelData*)malloc(iNumThreads*sizeof(MatMult_KernelData)); 1309 MatMult_KernelData** pdata = (MatMult_KernelData**)malloc(iNumThreads*sizeof(MatMult_KernelData*)); 1310 1311 iindex = 0; 1312 for(i=0; i<iNumThreads;i++) { 1313 S = (PetscBool)(i<R); 1314 kerneldatap[i].matdata = aa; 1315 kerneldatap[i].vecdata = x; 1316 kerneldatap[i].vecout = y; 1317 kerneldatap[i].colindnz = aj; 1318 kerneldatap[i].rownumnz = ii + iindex; 1319 kerneldatap[i].numrows = S?Q+1:Q; 1320 kerneldatap[i].specidx = PETSC_NULL; 1321 kerneldatap[i].nzr = iindex; /* serves as the 'base' row (needed to access correctly into output vector y) */ 1322 pdata[i] = &kerneldatap[i]; 1323 iindex += kerneldatap[i].numrows; 1324 } 1325 MainJob(MatMult_Kernel,(void**)pdata,iNumThreads); 1326 /* collect results */ 1327 for(i=0; i<iNumThreads; i++) { 1328 nonzerorow += kerneldatap[i].nzr; 1329 } 1330 free(kerneldatap); 1331 free(pdata); 1332 #endif 1333 } 1334 1335 ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr); 1336 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1337 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 1338 PetscFunctionReturn(0); 1339 } 1340 /* ******************* */ 1341 #endif 1342 1343 #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h> 1344 #undef __FUNCT__ 1345 #define __FUNCT__ "MatMultAdd_SeqAIJ" 1346 PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1347 { 1348 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1349 PetscScalar *y,*z; 1350 const PetscScalar *x; 1351 const MatScalar *aa; 1352 PetscErrorCode ierr; 1353 PetscInt m = A->rmap->n,*aj,*ii; 1354 PetscInt n,i,*ridx=PETSC_NULL; 1355 PetscScalar sum; 1356 PetscBool usecprow=a->compressedrow.use; 1357 1358 PetscFunctionBegin; 1359 ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr); 1360 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 1361 if (zz != yy) { 1362 ierr = VecGetArray(zz,&z);CHKERRQ(ierr); 1363 } else { 1364 z = y; 1365 } 1366 1367 aj = a->j; 1368 aa = a->a; 1369 ii = a->i; 1370 if (usecprow){ /* use compressed row format */ 1371 if (zz != yy){ 1372 ierr = PetscMemcpy(z,y,m*sizeof(PetscScalar));CHKERRQ(ierr); 1373 } 1374 m = a->compressedrow.nrows; 1375 ii = a->compressedrow.i; 1376 ridx = a->compressedrow.rindex; 1377 for (i=0; i<m; i++){ 1378 n = ii[i+1] - ii[i]; 1379 aj = a->j + ii[i]; 1380 aa = a->a + ii[i]; 1381 sum = y[*ridx]; 1382 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1383 z[*ridx++] = sum; 1384 } 1385 } else { /* do not use compressed row format */ 1386 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ) 1387 fortranmultaddaij_(&m,x,ii,aj,aa,y,z); 1388 #else 1389 for (i=0; i<m; i++) { 1390 n = ii[i+1] - ii[i]; 1391 aj = a->j + ii[i]; 1392 aa = a->a + ii[i]; 1393 sum = y[i]; 1394 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1395 z[i] = sum; 1396 } 1397 #endif 1398 } 1399 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1400 ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr); 1401 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 1402 if (zz != yy) { 1403 ierr = VecRestoreArray(zz,&z);CHKERRQ(ierr); 1404 } 1405 #if defined(PETSC_HAVE_CUSP) 1406 /* 1407 ierr = VecView(xx,0);CHKERRQ(ierr); 1408 ierr = VecView(zz,0);CHKERRQ(ierr); 1409 ierr = MatView(A,0);CHKERRQ(ierr); 1410 */ 1411 #endif 1412 PetscFunctionReturn(0); 1413 } 1414 1415 /* 1416 Adds diagonal pointers to sparse matrix structure. 1417 */ 1418 #undef __FUNCT__ 1419 #define __FUNCT__ "MatMarkDiagonal_SeqAIJ" 1420 PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A) 1421 { 1422 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1423 PetscErrorCode ierr; 1424 PetscInt i,j,m = A->rmap->n; 1425 1426 PetscFunctionBegin; 1427 if (!a->diag) { 1428 ierr = PetscMalloc(m*sizeof(PetscInt),&a->diag);CHKERRQ(ierr); 1429 ierr = PetscLogObjectMemory(A, m*sizeof(PetscInt));CHKERRQ(ierr); 1430 } 1431 for (i=0; i<A->rmap->n; i++) { 1432 a->diag[i] = a->i[i+1]; 1433 for (j=a->i[i]; j<a->i[i+1]; j++) { 1434 if (a->j[j] == i) { 1435 a->diag[i] = j; 1436 break; 1437 } 1438 } 1439 } 1440 PetscFunctionReturn(0); 1441 } 1442 1443 /* 1444 Checks for missing diagonals 1445 */ 1446 #undef __FUNCT__ 1447 #define __FUNCT__ "MatMissingDiagonal_SeqAIJ" 1448 PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool *missing,PetscInt *d) 1449 { 1450 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1451 PetscInt *diag,*jj = a->j,i; 1452 1453 PetscFunctionBegin; 1454 *missing = PETSC_FALSE; 1455 if (A->rmap->n > 0 && !jj) { 1456 *missing = PETSC_TRUE; 1457 if (d) *d = 0; 1458 PetscInfo(A,"Matrix has no entries therefor is missing diagonal"); 1459 } else { 1460 diag = a->diag; 1461 for (i=0; i<A->rmap->n; i++) { 1462 if (jj[diag[i]] != i) { 1463 *missing = PETSC_TRUE; 1464 if (d) *d = i; 1465 PetscInfo1(A,"Matrix is missing diagonal number %D",i); 1466 } 1467 } 1468 } 1469 PetscFunctionReturn(0); 1470 } 1471 1472 EXTERN_C_BEGIN 1473 #undef __FUNCT__ 1474 #define __FUNCT__ "MatInvertDiagonal_SeqAIJ" 1475 PetscErrorCode MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift) 1476 { 1477 Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 1478 PetscErrorCode ierr; 1479 PetscInt i,*diag,m = A->rmap->n; 1480 MatScalar *v = a->a; 1481 PetscScalar *idiag,*mdiag; 1482 1483 PetscFunctionBegin; 1484 if (a->idiagvalid) PetscFunctionReturn(0); 1485 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 1486 diag = a->diag; 1487 if (!a->idiag) { 1488 ierr = PetscMalloc3(m,PetscScalar,&a->idiag,m,PetscScalar,&a->mdiag,m,PetscScalar,&a->ssor_work);CHKERRQ(ierr); 1489 ierr = PetscLogObjectMemory(A, 3*m*sizeof(PetscScalar));CHKERRQ(ierr); 1490 v = a->a; 1491 } 1492 mdiag = a->mdiag; 1493 idiag = a->idiag; 1494 1495 if (omega == 1.0 && !PetscAbsScalar(fshift)) { 1496 for (i=0; i<m; i++) { 1497 mdiag[i] = v[diag[i]]; 1498 if (!PetscAbsScalar(mdiag[i])) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i); 1499 idiag[i] = 1.0/v[diag[i]]; 1500 } 1501 ierr = PetscLogFlops(m);CHKERRQ(ierr); 1502 } else { 1503 for (i=0; i<m; i++) { 1504 mdiag[i] = v[diag[i]]; 1505 idiag[i] = omega/(fshift + v[diag[i]]); 1506 } 1507 ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr); 1508 } 1509 a->idiagvalid = PETSC_TRUE; 1510 PetscFunctionReturn(0); 1511 } 1512 EXTERN_C_END 1513 1514 #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h> 1515 #undef __FUNCT__ 1516 #define __FUNCT__ "MatSOR_SeqAIJ" 1517 PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 1518 { 1519 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1520 PetscScalar *x,d,sum,*t,scale; 1521 const MatScalar *v = a->a,*idiag=0,*mdiag; 1522 const PetscScalar *b, *bs,*xb, *ts; 1523 PetscErrorCode ierr; 1524 PetscInt n = A->cmap->n,m = A->rmap->n,i; 1525 const PetscInt *idx,*diag; 1526 1527 PetscFunctionBegin; 1528 its = its*lits; 1529 1530 if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */ 1531 if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);} 1532 a->fshift = fshift; 1533 a->omega = omega; 1534 1535 diag = a->diag; 1536 t = a->ssor_work; 1537 idiag = a->idiag; 1538 mdiag = a->mdiag; 1539 1540 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 1541 ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr); 1542 CHKMEMQ; 1543 /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */ 1544 if (flag == SOR_APPLY_UPPER) { 1545 /* apply (U + D/omega) to the vector */ 1546 bs = b; 1547 for (i=0; i<m; i++) { 1548 d = fshift + mdiag[i]; 1549 n = a->i[i+1] - diag[i] - 1; 1550 idx = a->j + diag[i] + 1; 1551 v = a->a + diag[i] + 1; 1552 sum = b[i]*d/omega; 1553 PetscSparseDensePlusDot(sum,bs,v,idx,n); 1554 x[i] = sum; 1555 } 1556 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1557 ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr); 1558 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 1559 PetscFunctionReturn(0); 1560 } 1561 1562 if (flag == SOR_APPLY_LOWER) { 1563 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented"); 1564 } else if (flag & SOR_EISENSTAT) { 1565 /* Let A = L + U + D; where L is lower trianglar, 1566 U is upper triangular, E = D/omega; This routine applies 1567 1568 (L + E)^{-1} A (U + E)^{-1} 1569 1570 to a vector efficiently using Eisenstat's trick. 1571 */ 1572 scale = (2.0/omega) - 1.0; 1573 1574 /* x = (E + U)^{-1} b */ 1575 for (i=m-1; i>=0; i--) { 1576 n = a->i[i+1] - diag[i] - 1; 1577 idx = a->j + diag[i] + 1; 1578 v = a->a + diag[i] + 1; 1579 sum = b[i]; 1580 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1581 x[i] = sum*idiag[i]; 1582 } 1583 1584 /* t = b - (2*E - D)x */ 1585 v = a->a; 1586 for (i=0; i<m; i++) { t[i] = b[i] - scale*(v[*diag++])*x[i]; } 1587 1588 /* t = (E + L)^{-1}t */ 1589 ts = t; 1590 diag = a->diag; 1591 for (i=0; i<m; i++) { 1592 n = diag[i] - a->i[i]; 1593 idx = a->j + a->i[i]; 1594 v = a->a + a->i[i]; 1595 sum = t[i]; 1596 PetscSparseDenseMinusDot(sum,ts,v,idx,n); 1597 t[i] = sum*idiag[i]; 1598 /* x = x + t */ 1599 x[i] += t[i]; 1600 } 1601 1602 ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr); 1603 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1604 ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr); 1605 PetscFunctionReturn(0); 1606 } 1607 if (flag & SOR_ZERO_INITIAL_GUESS) { 1608 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 1609 for (i=0; i<m; i++) { 1610 n = diag[i] - a->i[i]; 1611 idx = a->j + a->i[i]; 1612 v = a->a + a->i[i]; 1613 sum = b[i]; 1614 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1615 t[i] = sum; 1616 x[i] = sum*idiag[i]; 1617 } 1618 xb = t; 1619 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 1620 } else xb = b; 1621 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 1622 for (i=m-1; i>=0; i--) { 1623 n = a->i[i+1] - diag[i] - 1; 1624 idx = a->j + diag[i] + 1; 1625 v = a->a + diag[i] + 1; 1626 sum = xb[i]; 1627 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1628 if (xb == b) { 1629 x[i] = sum*idiag[i]; 1630 } else { 1631 x[i] = (1-omega)*x[i] + sum*idiag[i]; 1632 } 1633 } 1634 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 1635 } 1636 its--; 1637 } 1638 while (its--) { 1639 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 1640 for (i=0; i<m; i++) { 1641 n = a->i[i+1] - a->i[i]; 1642 idx = a->j + a->i[i]; 1643 v = a->a + a->i[i]; 1644 sum = b[i]; 1645 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1646 x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i]; 1647 } 1648 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1649 } 1650 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 1651 for (i=m-1; i>=0; i--) { 1652 n = a->i[i+1] - a->i[i]; 1653 idx = a->j + a->i[i]; 1654 v = a->a + a->i[i]; 1655 sum = b[i]; 1656 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1657 x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i]; 1658 } 1659 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1660 } 1661 } 1662 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1663 ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr); 1664 CHKMEMQ; PetscFunctionReturn(0); 1665 } 1666 1667 1668 #undef __FUNCT__ 1669 #define __FUNCT__ "MatGetInfo_SeqAIJ" 1670 PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info) 1671 { 1672 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1673 1674 PetscFunctionBegin; 1675 info->block_size = 1.0; 1676 info->nz_allocated = (double)a->maxnz; 1677 info->nz_used = (double)a->nz; 1678 info->nz_unneeded = (double)(a->maxnz - a->nz); 1679 info->assemblies = (double)A->num_ass; 1680 info->mallocs = (double)A->info.mallocs; 1681 info->memory = ((PetscObject)A)->mem; 1682 if (A->factortype) { 1683 info->fill_ratio_given = A->info.fill_ratio_given; 1684 info->fill_ratio_needed = A->info.fill_ratio_needed; 1685 info->factor_mallocs = A->info.factor_mallocs; 1686 } else { 1687 info->fill_ratio_given = 0; 1688 info->fill_ratio_needed = 0; 1689 info->factor_mallocs = 0; 1690 } 1691 PetscFunctionReturn(0); 1692 } 1693 1694 #undef __FUNCT__ 1695 #define __FUNCT__ "MatZeroRows_SeqAIJ" 1696 PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1697 { 1698 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1699 PetscInt i,m = A->rmap->n - 1,d = 0; 1700 PetscErrorCode ierr; 1701 const PetscScalar *xx; 1702 PetscScalar *bb; 1703 PetscBool missing; 1704 1705 PetscFunctionBegin; 1706 if (x && b) { 1707 ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 1708 ierr = VecGetArray(b,&bb);CHKERRQ(ierr); 1709 for (i=0; i<N; i++) { 1710 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 1711 bb[rows[i]] = diag*xx[rows[i]]; 1712 } 1713 ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 1714 ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr); 1715 } 1716 1717 if (a->keepnonzeropattern) { 1718 for (i=0; i<N; i++) { 1719 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 1720 ierr = PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));CHKERRQ(ierr); 1721 } 1722 if (diag != 0.0) { 1723 ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr); 1724 if (missing) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D",d); 1725 for (i=0; i<N; i++) { 1726 a->a[a->diag[rows[i]]] = diag; 1727 } 1728 } 1729 A->same_nonzero = PETSC_TRUE; 1730 } else { 1731 if (diag != 0.0) { 1732 for (i=0; i<N; i++) { 1733 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 1734 if (a->ilen[rows[i]] > 0) { 1735 a->ilen[rows[i]] = 1; 1736 a->a[a->i[rows[i]]] = diag; 1737 a->j[a->i[rows[i]]] = rows[i]; 1738 } else { /* in case row was completely empty */ 1739 ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr); 1740 } 1741 } 1742 } else { 1743 for (i=0; i<N; i++) { 1744 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 1745 a->ilen[rows[i]] = 0; 1746 } 1747 } 1748 A->same_nonzero = PETSC_FALSE; 1749 } 1750 ierr = MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1751 PetscFunctionReturn(0); 1752 } 1753 1754 #undef __FUNCT__ 1755 #define __FUNCT__ "MatZeroRowsColumns_SeqAIJ" 1756 PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1757 { 1758 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1759 PetscInt i,j,m = A->rmap->n - 1,d = 0; 1760 PetscErrorCode ierr; 1761 PetscBool missing,*zeroed,vecs = PETSC_FALSE; 1762 const PetscScalar *xx; 1763 PetscScalar *bb; 1764 1765 PetscFunctionBegin; 1766 if (x && b) { 1767 ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 1768 ierr = VecGetArray(b,&bb);CHKERRQ(ierr); 1769 vecs = PETSC_TRUE; 1770 } 1771 ierr = PetscMalloc(A->rmap->n*sizeof(PetscBool),&zeroed);CHKERRQ(ierr); 1772 ierr = PetscMemzero(zeroed,A->rmap->n*sizeof(PetscBool));CHKERRQ(ierr); 1773 for (i=0; i<N; i++) { 1774 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 1775 ierr = PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));CHKERRQ(ierr); 1776 zeroed[rows[i]] = PETSC_TRUE; 1777 } 1778 for (i=0; i<A->rmap->n; i++) { 1779 if (!zeroed[i]) { 1780 for (j=a->i[i]; j<a->i[i+1]; j++) { 1781 if (zeroed[a->j[j]]) { 1782 if (vecs) bb[i] -= a->a[j]*xx[a->j[j]]; 1783 a->a[j] = 0.0; 1784 } 1785 } 1786 } else if (vecs) bb[i] = diag*xx[i]; 1787 } 1788 if (x && b) { 1789 ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 1790 ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr); 1791 } 1792 ierr = PetscFree(zeroed);CHKERRQ(ierr); 1793 if (diag != 0.0) { 1794 ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr); 1795 if (missing) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D",d); 1796 for (i=0; i<N; i++) { 1797 a->a[a->diag[rows[i]]] = diag; 1798 } 1799 } 1800 A->same_nonzero = PETSC_TRUE; 1801 ierr = MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1802 PetscFunctionReturn(0); 1803 } 1804 1805 #undef __FUNCT__ 1806 #define __FUNCT__ "MatGetRow_SeqAIJ" 1807 PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 1808 { 1809 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1810 PetscInt *itmp; 1811 1812 PetscFunctionBegin; 1813 if (row < 0 || row >= A->rmap->n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row); 1814 1815 *nz = a->i[row+1] - a->i[row]; 1816 if (v) *v = a->a + a->i[row]; 1817 if (idx) { 1818 itmp = a->j + a->i[row]; 1819 if (*nz) { 1820 *idx = itmp; 1821 } 1822 else *idx = 0; 1823 } 1824 PetscFunctionReturn(0); 1825 } 1826 1827 /* remove this function? */ 1828 #undef __FUNCT__ 1829 #define __FUNCT__ "MatRestoreRow_SeqAIJ" 1830 PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 1831 { 1832 PetscFunctionBegin; 1833 PetscFunctionReturn(0); 1834 } 1835 1836 #undef __FUNCT__ 1837 #define __FUNCT__ "MatNorm_SeqAIJ" 1838 PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm) 1839 { 1840 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1841 MatScalar *v = a->a; 1842 PetscReal sum = 0.0; 1843 PetscErrorCode ierr; 1844 PetscInt i,j; 1845 1846 PetscFunctionBegin; 1847 if (type == NORM_FROBENIUS) { 1848 for (i=0; i<a->nz; i++) { 1849 #if defined(PETSC_USE_COMPLEX) 1850 sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 1851 #else 1852 sum += (*v)*(*v); v++; 1853 #endif 1854 } 1855 *nrm = PetscSqrtReal(sum); 1856 } else if (type == NORM_1) { 1857 PetscReal *tmp; 1858 PetscInt *jj = a->j; 1859 ierr = PetscMalloc((A->cmap->n+1)*sizeof(PetscReal),&tmp);CHKERRQ(ierr); 1860 ierr = PetscMemzero(tmp,A->cmap->n*sizeof(PetscReal));CHKERRQ(ierr); 1861 *nrm = 0.0; 1862 for (j=0; j<a->nz; j++) { 1863 tmp[*jj++] += PetscAbsScalar(*v); v++; 1864 } 1865 for (j=0; j<A->cmap->n; j++) { 1866 if (tmp[j] > *nrm) *nrm = tmp[j]; 1867 } 1868 ierr = PetscFree(tmp);CHKERRQ(ierr); 1869 } else if (type == NORM_INFINITY) { 1870 *nrm = 0.0; 1871 for (j=0; j<A->rmap->n; j++) { 1872 v = a->a + a->i[j]; 1873 sum = 0.0; 1874 for (i=0; i<a->i[j+1]-a->i[j]; i++) { 1875 sum += PetscAbsScalar(*v); v++; 1876 } 1877 if (sum > *nrm) *nrm = sum; 1878 } 1879 } else { 1880 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm"); 1881 } 1882 PetscFunctionReturn(0); 1883 } 1884 1885 #undef __FUNCT__ 1886 #define __FUNCT__ "MatTranspose_SeqAIJ" 1887 PetscErrorCode MatTranspose_SeqAIJ(Mat A,MatReuse reuse,Mat *B) 1888 { 1889 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1890 Mat C; 1891 PetscErrorCode ierr; 1892 PetscInt i,*aj = a->j,*ai = a->i,m = A->rmap->n,len,*col; 1893 MatScalar *array = a->a; 1894 1895 PetscFunctionBegin; 1896 if (reuse == MAT_REUSE_MATRIX && A == *B && m != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Square matrix only for in-place"); 1897 1898 if (reuse == MAT_INITIAL_MATRIX || *B == A) { 1899 ierr = PetscMalloc((1+A->cmap->n)*sizeof(PetscInt),&col);CHKERRQ(ierr); 1900 ierr = PetscMemzero(col,(1+A->cmap->n)*sizeof(PetscInt));CHKERRQ(ierr); 1901 1902 for (i=0; i<ai[m]; i++) col[aj[i]] += 1; 1903 ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr); 1904 ierr = MatSetSizes(C,A->cmap->n,m,A->cmap->n,m);CHKERRQ(ierr); 1905 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 1906 ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,col);CHKERRQ(ierr); 1907 ierr = PetscFree(col);CHKERRQ(ierr); 1908 } else { 1909 C = *B; 1910 } 1911 1912 for (i=0; i<m; i++) { 1913 len = ai[i+1]-ai[i]; 1914 ierr = MatSetValues_SeqAIJ(C,len,aj,1,&i,array,INSERT_VALUES);CHKERRQ(ierr); 1915 array += len; 1916 aj += len; 1917 } 1918 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1919 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1920 1921 if (reuse == MAT_INITIAL_MATRIX || *B != A) { 1922 *B = C; 1923 } else { 1924 ierr = MatHeaderMerge(A,C);CHKERRQ(ierr); 1925 } 1926 PetscFunctionReturn(0); 1927 } 1928 1929 EXTERN_C_BEGIN 1930 #undef __FUNCT__ 1931 #define __FUNCT__ "MatIsTranspose_SeqAIJ" 1932 PetscErrorCode MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f) 1933 { 1934 Mat_SeqAIJ *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data; 1935 PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr; 1936 MatScalar *va,*vb; 1937 PetscErrorCode ierr; 1938 PetscInt ma,na,mb,nb, i; 1939 1940 PetscFunctionBegin; 1941 bij = (Mat_SeqAIJ *) B->data; 1942 1943 ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr); 1944 ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr); 1945 if (ma!=nb || na!=mb){ 1946 *f = PETSC_FALSE; 1947 PetscFunctionReturn(0); 1948 } 1949 aii = aij->i; bii = bij->i; 1950 adx = aij->j; bdx = bij->j; 1951 va = aij->a; vb = bij->a; 1952 ierr = PetscMalloc(ma*sizeof(PetscInt),&aptr);CHKERRQ(ierr); 1953 ierr = PetscMalloc(mb*sizeof(PetscInt),&bptr);CHKERRQ(ierr); 1954 for (i=0; i<ma; i++) aptr[i] = aii[i]; 1955 for (i=0; i<mb; i++) bptr[i] = bii[i]; 1956 1957 *f = PETSC_TRUE; 1958 for (i=0; i<ma; i++) { 1959 while (aptr[i]<aii[i+1]) { 1960 PetscInt idc,idr; 1961 PetscScalar vc,vr; 1962 /* column/row index/value */ 1963 idc = adx[aptr[i]]; 1964 idr = bdx[bptr[idc]]; 1965 vc = va[aptr[i]]; 1966 vr = vb[bptr[idc]]; 1967 if (i!=idr || PetscAbsScalar(vc-vr) > tol) { 1968 *f = PETSC_FALSE; 1969 goto done; 1970 } else { 1971 aptr[i]++; 1972 if (B || i!=idc) bptr[idc]++; 1973 } 1974 } 1975 } 1976 done: 1977 ierr = PetscFree(aptr);CHKERRQ(ierr); 1978 ierr = PetscFree(bptr);CHKERRQ(ierr); 1979 PetscFunctionReturn(0); 1980 } 1981 EXTERN_C_END 1982 1983 EXTERN_C_BEGIN 1984 #undef __FUNCT__ 1985 #define __FUNCT__ "MatIsHermitianTranspose_SeqAIJ" 1986 PetscErrorCode MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f) 1987 { 1988 Mat_SeqAIJ *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data; 1989 PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr; 1990 MatScalar *va,*vb; 1991 PetscErrorCode ierr; 1992 PetscInt ma,na,mb,nb, i; 1993 1994 PetscFunctionBegin; 1995 bij = (Mat_SeqAIJ *) B->data; 1996 1997 ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr); 1998 ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr); 1999 if (ma!=nb || na!=mb){ 2000 *f = PETSC_FALSE; 2001 PetscFunctionReturn(0); 2002 } 2003 aii = aij->i; bii = bij->i; 2004 adx = aij->j; bdx = bij->j; 2005 va = aij->a; vb = bij->a; 2006 ierr = PetscMalloc(ma*sizeof(PetscInt),&aptr);CHKERRQ(ierr); 2007 ierr = PetscMalloc(mb*sizeof(PetscInt),&bptr);CHKERRQ(ierr); 2008 for (i=0; i<ma; i++) aptr[i] = aii[i]; 2009 for (i=0; i<mb; i++) bptr[i] = bii[i]; 2010 2011 *f = PETSC_TRUE; 2012 for (i=0; i<ma; i++) { 2013 while (aptr[i]<aii[i+1]) { 2014 PetscInt idc,idr; 2015 PetscScalar vc,vr; 2016 /* column/row index/value */ 2017 idc = adx[aptr[i]]; 2018 idr = bdx[bptr[idc]]; 2019 vc = va[aptr[i]]; 2020 vr = vb[bptr[idc]]; 2021 if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) { 2022 *f = PETSC_FALSE; 2023 goto done; 2024 } else { 2025 aptr[i]++; 2026 if (B || i!=idc) bptr[idc]++; 2027 } 2028 } 2029 } 2030 done: 2031 ierr = PetscFree(aptr);CHKERRQ(ierr); 2032 ierr = PetscFree(bptr);CHKERRQ(ierr); 2033 PetscFunctionReturn(0); 2034 } 2035 EXTERN_C_END 2036 2037 #undef __FUNCT__ 2038 #define __FUNCT__ "MatIsSymmetric_SeqAIJ" 2039 PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool *f) 2040 { 2041 PetscErrorCode ierr; 2042 PetscFunctionBegin; 2043 ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr); 2044 PetscFunctionReturn(0); 2045 } 2046 2047 #undef __FUNCT__ 2048 #define __FUNCT__ "MatIsHermitian_SeqAIJ" 2049 PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool *f) 2050 { 2051 PetscErrorCode ierr; 2052 PetscFunctionBegin; 2053 ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr); 2054 PetscFunctionReturn(0); 2055 } 2056 2057 #undef __FUNCT__ 2058 #define __FUNCT__ "MatDiagonalScale_SeqAIJ" 2059 PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr) 2060 { 2061 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2062 PetscScalar *l,*r,x; 2063 MatScalar *v; 2064 PetscErrorCode ierr; 2065 PetscInt i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz,*jj; 2066 2067 PetscFunctionBegin; 2068 if (ll) { 2069 /* The local size is used so that VecMPI can be passed to this routine 2070 by MatDiagonalScale_MPIAIJ */ 2071 ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr); 2072 if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length"); 2073 ierr = VecGetArray(ll,&l);CHKERRQ(ierr); 2074 v = a->a; 2075 for (i=0; i<m; i++) { 2076 x = l[i]; 2077 M = a->i[i+1] - a->i[i]; 2078 for (j=0; j<M; j++) { (*v++) *= x;} 2079 } 2080 ierr = VecRestoreArray(ll,&l);CHKERRQ(ierr); 2081 ierr = PetscLogFlops(nz);CHKERRQ(ierr); 2082 } 2083 if (rr) { 2084 ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr); 2085 if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length"); 2086 ierr = VecGetArray(rr,&r);CHKERRQ(ierr); 2087 v = a->a; jj = a->j; 2088 for (i=0; i<nz; i++) { 2089 (*v++) *= r[*jj++]; 2090 } 2091 ierr = VecRestoreArray(rr,&r);CHKERRQ(ierr); 2092 ierr = PetscLogFlops(nz);CHKERRQ(ierr); 2093 } 2094 a->idiagvalid = PETSC_FALSE; 2095 a->ibdiagvalid = PETSC_FALSE; 2096 PetscFunctionReturn(0); 2097 } 2098 2099 #undef __FUNCT__ 2100 #define __FUNCT__ "MatGetSubMatrix_SeqAIJ" 2101 PetscErrorCode MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B) 2102 { 2103 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*c; 2104 PetscErrorCode ierr; 2105 PetscInt *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens; 2106 PetscInt row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi; 2107 const PetscInt *irow,*icol; 2108 PetscInt nrows,ncols; 2109 PetscInt *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen; 2110 MatScalar *a_new,*mat_a; 2111 Mat C; 2112 PetscBool stride,sorted; 2113 2114 PetscFunctionBegin; 2115 ierr = ISSorted(isrow,&sorted);CHKERRQ(ierr); 2116 if (!sorted) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"ISrow is not sorted"); 2117 ierr = ISSorted(iscol,&sorted);CHKERRQ(ierr); 2118 if (!sorted) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"IScol is not sorted"); 2119 2120 ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr); 2121 ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr); 2122 ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr); 2123 2124 ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr); 2125 ierr = PetscTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr); 2126 if (stride && step == 1) { 2127 /* special case of contiguous rows */ 2128 ierr = PetscMalloc2(nrows,PetscInt,&lens,nrows,PetscInt,&starts);CHKERRQ(ierr); 2129 /* loop over new rows determining lens and starting points */ 2130 for (i=0; i<nrows; i++) { 2131 kstart = ai[irow[i]]; 2132 kend = kstart + ailen[irow[i]]; 2133 for (k=kstart; k<kend; k++) { 2134 if (aj[k] >= first) { 2135 starts[i] = k; 2136 break; 2137 } 2138 } 2139 sum = 0; 2140 while (k < kend) { 2141 if (aj[k++] >= first+ncols) break; 2142 sum++; 2143 } 2144 lens[i] = sum; 2145 } 2146 /* create submatrix */ 2147 if (scall == MAT_REUSE_MATRIX) { 2148 PetscInt n_cols,n_rows; 2149 ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr); 2150 if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size"); 2151 ierr = MatZeroEntries(*B);CHKERRQ(ierr); 2152 C = *B; 2153 } else { 2154 ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr); 2155 ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 2156 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 2157 ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr); 2158 } 2159 c = (Mat_SeqAIJ*)C->data; 2160 2161 /* loop over rows inserting into submatrix */ 2162 a_new = c->a; 2163 j_new = c->j; 2164 i_new = c->i; 2165 2166 for (i=0; i<nrows; i++) { 2167 ii = starts[i]; 2168 lensi = lens[i]; 2169 for (k=0; k<lensi; k++) { 2170 *j_new++ = aj[ii+k] - first; 2171 } 2172 ierr = PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(PetscScalar));CHKERRQ(ierr); 2173 a_new += lensi; 2174 i_new[i+1] = i_new[i] + lensi; 2175 c->ilen[i] = lensi; 2176 } 2177 ierr = PetscFree2(lens,starts);CHKERRQ(ierr); 2178 } else { 2179 ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr); 2180 ierr = PetscMalloc(oldcols*sizeof(PetscInt),&smap);CHKERRQ(ierr); 2181 ierr = PetscMemzero(smap,oldcols*sizeof(PetscInt));CHKERRQ(ierr); 2182 ierr = PetscMalloc((1+nrows)*sizeof(PetscInt),&lens);CHKERRQ(ierr); 2183 for (i=0; i<ncols; i++) { 2184 #if defined(PETSC_USE_DEBUG) 2185 if (icol[i] >= oldcols) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Requesting column beyond largest column icol[%D] %D <= A->cmap->n %D",i,icol[i],oldcols); 2186 #endif 2187 smap[icol[i]] = i+1; 2188 } 2189 2190 /* determine lens of each row */ 2191 for (i=0; i<nrows; i++) { 2192 kstart = ai[irow[i]]; 2193 kend = kstart + a->ilen[irow[i]]; 2194 lens[i] = 0; 2195 for (k=kstart; k<kend; k++) { 2196 if (smap[aj[k]]) { 2197 lens[i]++; 2198 } 2199 } 2200 } 2201 /* Create and fill new matrix */ 2202 if (scall == MAT_REUSE_MATRIX) { 2203 PetscBool equal; 2204 2205 c = (Mat_SeqAIJ *)((*B)->data); 2206 if ((*B)->rmap->n != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size"); 2207 ierr = PetscMemcmp(c->ilen,lens,(*B)->rmap->n*sizeof(PetscInt),&equal);CHKERRQ(ierr); 2208 if (!equal) { 2209 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros"); 2210 } 2211 ierr = PetscMemzero(c->ilen,(*B)->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 2212 C = *B; 2213 } else { 2214 ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr); 2215 ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 2216 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 2217 ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr); 2218 } 2219 c = (Mat_SeqAIJ *)(C->data); 2220 for (i=0; i<nrows; i++) { 2221 row = irow[i]; 2222 kstart = ai[row]; 2223 kend = kstart + a->ilen[row]; 2224 mat_i = c->i[i]; 2225 mat_j = c->j + mat_i; 2226 mat_a = c->a + mat_i; 2227 mat_ilen = c->ilen + i; 2228 for (k=kstart; k<kend; k++) { 2229 if ((tcol=smap[a->j[k]])) { 2230 *mat_j++ = tcol - 1; 2231 *mat_a++ = a->a[k]; 2232 (*mat_ilen)++; 2233 2234 } 2235 } 2236 } 2237 /* Free work space */ 2238 ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr); 2239 ierr = PetscFree(smap);CHKERRQ(ierr); 2240 ierr = PetscFree(lens);CHKERRQ(ierr); 2241 } 2242 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2243 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2244 2245 ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr); 2246 *B = C; 2247 PetscFunctionReturn(0); 2248 } 2249 2250 #undef __FUNCT__ 2251 #define __FUNCT__ "MatGetMultiProcBlock_SeqAIJ" 2252 PetscErrorCode MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,Mat* subMat) 2253 { 2254 PetscErrorCode ierr; 2255 Mat B; 2256 2257 PetscFunctionBegin; 2258 ierr = MatCreate(subComm,&B);CHKERRQ(ierr); 2259 ierr = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr); 2260 ierr = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr); 2261 ierr = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr); 2262 *subMat = B; 2263 PetscFunctionReturn(0); 2264 } 2265 2266 #undef __FUNCT__ 2267 #define __FUNCT__ "MatILUFactor_SeqAIJ" 2268 PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info) 2269 { 2270 Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 2271 PetscErrorCode ierr; 2272 Mat outA; 2273 PetscBool row_identity,col_identity; 2274 2275 PetscFunctionBegin; 2276 if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu"); 2277 2278 ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr); 2279 ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr); 2280 2281 outA = inA; 2282 outA->factortype = MAT_FACTOR_LU; 2283 ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr); 2284 ierr = ISDestroy(&a->row);CHKERRQ(ierr); 2285 a->row = row; 2286 ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr); 2287 ierr = ISDestroy(&a->col);CHKERRQ(ierr); 2288 a->col = col; 2289 2290 /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */ 2291 ierr = ISDestroy(&a->icol);CHKERRQ(ierr); 2292 ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr); 2293 ierr = PetscLogObjectParent(inA,a->icol);CHKERRQ(ierr); 2294 2295 if (!a->solve_work) { /* this matrix may have been factored before */ 2296 ierr = PetscMalloc((inA->rmap->n+1)*sizeof(PetscScalar),&a->solve_work);CHKERRQ(ierr); 2297 ierr = PetscLogObjectMemory(inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr); 2298 } 2299 2300 ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr); 2301 if (row_identity && col_identity) { 2302 ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr); 2303 } else { 2304 ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr); 2305 } 2306 PetscFunctionReturn(0); 2307 } 2308 2309 #undef __FUNCT__ 2310 #define __FUNCT__ "MatScale_SeqAIJ" 2311 PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha) 2312 { 2313 Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 2314 PetscScalar oalpha = alpha; 2315 PetscErrorCode ierr; 2316 PetscBLASInt one = 1,bnz = PetscBLASIntCast(a->nz); 2317 2318 PetscFunctionBegin; 2319 BLASscal_(&bnz,&oalpha,a->a,&one); 2320 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 2321 a->idiagvalid = PETSC_FALSE; 2322 a->ibdiagvalid = PETSC_FALSE; 2323 PetscFunctionReturn(0); 2324 } 2325 2326 #undef __FUNCT__ 2327 #define __FUNCT__ "MatGetSubMatrices_SeqAIJ" 2328 PetscErrorCode MatGetSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[]) 2329 { 2330 PetscErrorCode ierr; 2331 PetscInt i; 2332 2333 PetscFunctionBegin; 2334 if (scall == MAT_INITIAL_MATRIX) { 2335 ierr = PetscMalloc((n+1)*sizeof(Mat),B);CHKERRQ(ierr); 2336 } 2337 2338 for (i=0; i<n; i++) { 2339 ierr = MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr); 2340 } 2341 PetscFunctionReturn(0); 2342 } 2343 2344 #undef __FUNCT__ 2345 #define __FUNCT__ "MatIncreaseOverlap_SeqAIJ" 2346 PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov) 2347 { 2348 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2349 PetscErrorCode ierr; 2350 PetscInt row,i,j,k,l,m,n,*nidx,isz,val; 2351 const PetscInt *idx; 2352 PetscInt start,end,*ai,*aj; 2353 PetscBT table; 2354 2355 PetscFunctionBegin; 2356 m = A->rmap->n; 2357 ai = a->i; 2358 aj = a->j; 2359 2360 if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used"); 2361 2362 ierr = PetscMalloc((m+1)*sizeof(PetscInt),&nidx);CHKERRQ(ierr); 2363 ierr = PetscBTCreate(m,table);CHKERRQ(ierr); 2364 2365 for (i=0; i<is_max; i++) { 2366 /* Initialize the two local arrays */ 2367 isz = 0; 2368 ierr = PetscBTMemzero(m,table);CHKERRQ(ierr); 2369 2370 /* Extract the indices, assume there can be duplicate entries */ 2371 ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr); 2372 ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr); 2373 2374 /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 2375 for (j=0; j<n ; ++j){ 2376 if(!PetscBTLookupSet(table,idx[j])) { nidx[isz++] = idx[j];} 2377 } 2378 ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr); 2379 ierr = ISDestroy(&is[i]);CHKERRQ(ierr); 2380 2381 k = 0; 2382 for (j=0; j<ov; j++){ /* for each overlap */ 2383 n = isz; 2384 for (; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */ 2385 row = nidx[k]; 2386 start = ai[row]; 2387 end = ai[row+1]; 2388 for (l = start; l<end ; l++){ 2389 val = aj[l] ; 2390 if (!PetscBTLookupSet(table,val)) {nidx[isz++] = val;} 2391 } 2392 } 2393 } 2394 ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr); 2395 } 2396 ierr = PetscBTDestroy(table);CHKERRQ(ierr); 2397 ierr = PetscFree(nidx);CHKERRQ(ierr); 2398 PetscFunctionReturn(0); 2399 } 2400 2401 /* -------------------------------------------------------------- */ 2402 #undef __FUNCT__ 2403 #define __FUNCT__ "MatPermute_SeqAIJ" 2404 PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B) 2405 { 2406 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2407 PetscErrorCode ierr; 2408 PetscInt i,nz = 0,m = A->rmap->n,n = A->cmap->n; 2409 const PetscInt *row,*col; 2410 PetscInt *cnew,j,*lens; 2411 IS icolp,irowp; 2412 PetscInt *cwork = PETSC_NULL; 2413 PetscScalar *vwork = PETSC_NULL; 2414 2415 PetscFunctionBegin; 2416 ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr); 2417 ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr); 2418 ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr); 2419 ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr); 2420 2421 /* determine lengths of permuted rows */ 2422 ierr = PetscMalloc((m+1)*sizeof(PetscInt),&lens);CHKERRQ(ierr); 2423 for (i=0; i<m; i++) { 2424 lens[row[i]] = a->i[i+1] - a->i[i]; 2425 } 2426 ierr = MatCreate(((PetscObject)A)->comm,B);CHKERRQ(ierr); 2427 ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr); 2428 ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr); 2429 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr); 2430 ierr = PetscFree(lens);CHKERRQ(ierr); 2431 2432 ierr = PetscMalloc(n*sizeof(PetscInt),&cnew);CHKERRQ(ierr); 2433 for (i=0; i<m; i++) { 2434 ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr); 2435 for (j=0; j<nz; j++) { cnew[j] = col[cwork[j]];} 2436 ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr); 2437 ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr); 2438 } 2439 ierr = PetscFree(cnew);CHKERRQ(ierr); 2440 (*B)->assembled = PETSC_FALSE; 2441 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2442 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2443 ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr); 2444 ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr); 2445 ierr = ISDestroy(&irowp);CHKERRQ(ierr); 2446 ierr = ISDestroy(&icolp);CHKERRQ(ierr); 2447 PetscFunctionReturn(0); 2448 } 2449 2450 #undef __FUNCT__ 2451 #define __FUNCT__ "MatCopy_SeqAIJ" 2452 PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str) 2453 { 2454 PetscErrorCode ierr; 2455 2456 PetscFunctionBegin; 2457 /* If the two matrices have the same copy implementation, use fast copy. */ 2458 if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) { 2459 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2460 Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 2461 2462 if (a->i[A->rmap->n] != b->i[B->rmap->n]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different"); 2463 ierr = PetscMemcpy(b->a,a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));CHKERRQ(ierr); 2464 } else { 2465 ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr); 2466 } 2467 PetscFunctionReturn(0); 2468 } 2469 2470 #undef __FUNCT__ 2471 #define __FUNCT__ "MatSetUpPreallocation_SeqAIJ" 2472 PetscErrorCode MatSetUpPreallocation_SeqAIJ(Mat A) 2473 { 2474 PetscErrorCode ierr; 2475 2476 PetscFunctionBegin; 2477 ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,0);CHKERRQ(ierr); 2478 PetscFunctionReturn(0); 2479 } 2480 2481 #undef __FUNCT__ 2482 #define __FUNCT__ "MatGetArray_SeqAIJ" 2483 PetscErrorCode MatGetArray_SeqAIJ(Mat A,PetscScalar *array[]) 2484 { 2485 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2486 PetscFunctionBegin; 2487 *array = a->a; 2488 PetscFunctionReturn(0); 2489 } 2490 2491 #undef __FUNCT__ 2492 #define __FUNCT__ "MatRestoreArray_SeqAIJ" 2493 PetscErrorCode MatRestoreArray_SeqAIJ(Mat A,PetscScalar *array[]) 2494 { 2495 PetscFunctionBegin; 2496 PetscFunctionReturn(0); 2497 } 2498 2499 #undef __FUNCT__ 2500 #define __FUNCT__ "MatFDColoringApply_SeqAIJ" 2501 PetscErrorCode MatFDColoringApply_SeqAIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx) 2502 { 2503 PetscErrorCode (*f)(void*,Vec,Vec,void*) = (PetscErrorCode (*)(void*,Vec,Vec,void *))coloring->f; 2504 PetscErrorCode ierr; 2505 PetscInt k,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2; 2506 PetscScalar dx,*y,*xx,*w3_array; 2507 PetscScalar *vscale_array; 2508 PetscReal epsilon = coloring->error_rel,umin = coloring->umin; 2509 Vec w1,w2,w3; 2510 void *fctx = coloring->fctx; 2511 PetscBool flg = PETSC_FALSE; 2512 2513 PetscFunctionBegin; 2514 if (!coloring->w1) { 2515 ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr); 2516 ierr = PetscLogObjectParent(coloring,coloring->w1);CHKERRQ(ierr); 2517 ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr); 2518 ierr = PetscLogObjectParent(coloring,coloring->w2);CHKERRQ(ierr); 2519 ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr); 2520 ierr = PetscLogObjectParent(coloring,coloring->w3);CHKERRQ(ierr); 2521 } 2522 w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3; 2523 2524 ierr = MatSetUnfactored(J);CHKERRQ(ierr); 2525 ierr = PetscOptionsGetBool(((PetscObject)coloring)->prefix,"-mat_fd_coloring_dont_rezero",&flg,PETSC_NULL);CHKERRQ(ierr); 2526 if (flg) { 2527 ierr = PetscInfo(coloring,"Not calling MatZeroEntries()\n");CHKERRQ(ierr); 2528 } else { 2529 PetscBool assembled; 2530 ierr = MatAssembled(J,&assembled);CHKERRQ(ierr); 2531 if (assembled) { 2532 ierr = MatZeroEntries(J);CHKERRQ(ierr); 2533 } 2534 } 2535 2536 ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr); 2537 ierr = VecGetSize(x1,&N);CHKERRQ(ierr); 2538 2539 /* 2540 This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets 2541 coloring->F for the coarser grids from the finest 2542 */ 2543 if (coloring->F) { 2544 ierr = VecGetLocalSize(coloring->F,&m1);CHKERRQ(ierr); 2545 ierr = VecGetLocalSize(w1,&m2);CHKERRQ(ierr); 2546 if (m1 != m2) { 2547 coloring->F = 0; 2548 } 2549 } 2550 2551 if (coloring->F) { 2552 w1 = coloring->F; 2553 coloring->F = 0; 2554 } else { 2555 ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 2556 ierr = (*f)(sctx,x1,w1,fctx);CHKERRQ(ierr); 2557 ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 2558 } 2559 2560 /* 2561 Compute all the scale factors and share with other processors 2562 */ 2563 ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start; 2564 ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start; 2565 for (k=0; k<coloring->ncolors; k++) { 2566 /* 2567 Loop over each column associated with color adding the 2568 perturbation to the vector w3. 2569 */ 2570 for (l=0; l<coloring->ncolumns[k]; l++) { 2571 col = coloring->columns[k][l]; /* column of the matrix we are probing for */ 2572 dx = xx[col]; 2573 if (dx == 0.0) dx = 1.0; 2574 #if !defined(PETSC_USE_COMPLEX) 2575 if (dx < umin && dx >= 0.0) dx = umin; 2576 else if (dx < 0.0 && dx > -umin) dx = -umin; 2577 #else 2578 if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin; 2579 else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin; 2580 #endif 2581 dx *= epsilon; 2582 vscale_array[col] = 1.0/dx; 2583 } 2584 } 2585 vscale_array = vscale_array + start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 2586 ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2587 ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2588 2589 /* ierr = VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD); 2590 ierr = VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/ 2591 2592 if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow; 2593 else vscaleforrow = coloring->columnsforrow; 2594 2595 ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 2596 /* 2597 Loop over each color 2598 */ 2599 for (k=0; k<coloring->ncolors; k++) { 2600 coloring->currentcolor = k; 2601 ierr = VecCopy(x1,w3);CHKERRQ(ierr); 2602 ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start; 2603 /* 2604 Loop over each column associated with color adding the 2605 perturbation to the vector w3. 2606 */ 2607 for (l=0; l<coloring->ncolumns[k]; l++) { 2608 col = coloring->columns[k][l]; /* column of the matrix we are probing for */ 2609 dx = xx[col]; 2610 if (dx == 0.0) dx = 1.0; 2611 #if !defined(PETSC_USE_COMPLEX) 2612 if (dx < umin && dx >= 0.0) dx = umin; 2613 else if (dx < 0.0 && dx > -umin) dx = -umin; 2614 #else 2615 if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin; 2616 else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin; 2617 #endif 2618 dx *= epsilon; 2619 if (!PetscAbsScalar(dx)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Computed 0 differencing parameter"); 2620 w3_array[col] += dx; 2621 } 2622 w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr); 2623 2624 /* 2625 Evaluate function at x1 + dx (here dx is a vector of perturbations) 2626 */ 2627 2628 ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 2629 ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr); 2630 ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 2631 ierr = VecAXPY(w2,-1.0,w1);CHKERRQ(ierr); 2632 2633 /* 2634 Loop over rows of vector, putting results into Jacobian matrix 2635 */ 2636 ierr = VecGetArray(w2,&y);CHKERRQ(ierr); 2637 for (l=0; l<coloring->nrows[k]; l++) { 2638 row = coloring->rows[k][l]; 2639 col = coloring->columnsforrow[k][l]; 2640 y[row] *= vscale_array[vscaleforrow[k][l]]; 2641 srow = row + start; 2642 ierr = MatSetValues_SeqAIJ(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr); 2643 } 2644 ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr); 2645 } 2646 coloring->currentcolor = k; 2647 ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 2648 xx = xx + start; ierr = VecRestoreArray(x1,&xx);CHKERRQ(ierr); 2649 ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2650 ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2651 PetscFunctionReturn(0); 2652 } 2653 2654 /* 2655 Computes the number of nonzeros per row needed for preallocation when X and Y 2656 have different nonzero structure. 2657 */ 2658 #undef __FUNCT__ 2659 #define __FUNCT__ "MatAXPYGetPreallocation_SeqAIJ" 2660 PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt* nnz) 2661 { 2662 PetscInt i,m=Y->rmap->N; 2663 Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data; 2664 Mat_SeqAIJ *y = (Mat_SeqAIJ*)Y->data; 2665 const PetscInt *xi = x->i,*yi = y->i; 2666 2667 PetscFunctionBegin; 2668 /* Set the number of nonzeros in the new matrix */ 2669 for(i=0; i<m; i++) { 2670 PetscInt j,k,nzx = xi[i+1] - xi[i],nzy = yi[i+1] - yi[i]; 2671 const PetscInt *xj = x->j+xi[i],*yj = y->j+yi[i]; 2672 nnz[i] = 0; 2673 for (j=0,k=0; j<nzx; j++) { /* Point in X */ 2674 for (; k<nzy && yj[k]<xj[j]; k++) nnz[i]++; /* Catch up to X */ 2675 if (k<nzy && yj[k]==xj[j]) k++; /* Skip duplicate */ 2676 nnz[i]++; 2677 } 2678 for (; k<nzy; k++) nnz[i]++; 2679 } 2680 PetscFunctionReturn(0); 2681 } 2682 2683 #undef __FUNCT__ 2684 #define __FUNCT__ "MatAXPY_SeqAIJ" 2685 PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str) 2686 { 2687 PetscErrorCode ierr; 2688 PetscInt i; 2689 Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data,*y = (Mat_SeqAIJ *)Y->data; 2690 PetscBLASInt one=1,bnz = PetscBLASIntCast(x->nz); 2691 2692 PetscFunctionBegin; 2693 if (str == SAME_NONZERO_PATTERN) { 2694 PetscScalar alpha = a; 2695 BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one); 2696 y->idiagvalid = PETSC_FALSE; 2697 y->ibdiagvalid = PETSC_FALSE; 2698 } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 2699 if (y->xtoy && y->XtoY != X) { 2700 ierr = PetscFree(y->xtoy);CHKERRQ(ierr); 2701 ierr = MatDestroy(&y->XtoY);CHKERRQ(ierr); 2702 } 2703 if (!y->xtoy) { /* get xtoy */ 2704 ierr = MatAXPYGetxtoy_Private(X->rmap->n,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);CHKERRQ(ierr); 2705 y->XtoY = X; 2706 ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 2707 } 2708 for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += a*(x->a[i]); 2709 ierr = PetscInfo3(Y,"ratio of nnz(X)/nnz(Y): %d/%d = %G\n",x->nz,y->nz,(PetscReal)(x->nz)/y->nz);CHKERRQ(ierr); 2710 } else { 2711 Mat B; 2712 PetscInt *nnz; 2713 ierr = PetscMalloc(Y->rmap->N*sizeof(PetscInt),&nnz);CHKERRQ(ierr); 2714 ierr = MatCreate(((PetscObject)Y)->comm,&B);CHKERRQ(ierr); 2715 ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr); 2716 ierr = MatSetSizes(B,Y->rmap->n,Y->cmap->n,Y->rmap->N,Y->cmap->N);CHKERRQ(ierr); 2717 ierr = MatSetType(B,(MatType) ((PetscObject)Y)->type_name);CHKERRQ(ierr); 2718 ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr); 2719 ierr = MatSeqAIJSetPreallocation(B,PETSC_NULL,nnz);CHKERRQ(ierr); 2720 ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr); 2721 ierr = MatHeaderReplace(Y,B);CHKERRQ(ierr); 2722 ierr = PetscFree(nnz);CHKERRQ(ierr); 2723 } 2724 PetscFunctionReturn(0); 2725 } 2726 2727 #undef __FUNCT__ 2728 #define __FUNCT__ "MatSetBlockSize_SeqAIJ" 2729 PetscErrorCode MatSetBlockSize_SeqAIJ(Mat A,PetscInt bs) 2730 { 2731 PetscErrorCode ierr; 2732 2733 PetscFunctionBegin; 2734 ierr = PetscLayoutSetBlockSize(A->rmap,bs);CHKERRQ(ierr); 2735 ierr = PetscLayoutSetBlockSize(A->cmap,bs);CHKERRQ(ierr); 2736 PetscFunctionReturn(0); 2737 } 2738 2739 #undef __FUNCT__ 2740 #define __FUNCT__ "MatConjugate_SeqAIJ" 2741 PetscErrorCode MatConjugate_SeqAIJ(Mat mat) 2742 { 2743 #if defined(PETSC_USE_COMPLEX) 2744 Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2745 PetscInt i,nz; 2746 PetscScalar *a; 2747 2748 PetscFunctionBegin; 2749 nz = aij->nz; 2750 a = aij->a; 2751 for (i=0; i<nz; i++) { 2752 a[i] = PetscConj(a[i]); 2753 } 2754 #else 2755 PetscFunctionBegin; 2756 #endif 2757 PetscFunctionReturn(0); 2758 } 2759 2760 #undef __FUNCT__ 2761 #define __FUNCT__ "MatGetRowMaxAbs_SeqAIJ" 2762 PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2763 { 2764 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2765 PetscErrorCode ierr; 2766 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2767 PetscReal atmp; 2768 PetscScalar *x; 2769 MatScalar *aa; 2770 2771 PetscFunctionBegin; 2772 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2773 aa = a->a; 2774 ai = a->i; 2775 aj = a->j; 2776 2777 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2778 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2779 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 2780 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2781 for (i=0; i<m; i++) { 2782 ncols = ai[1] - ai[0]; ai++; 2783 x[i] = 0.0; 2784 for (j=0; j<ncols; j++){ 2785 atmp = PetscAbsScalar(*aa); 2786 if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;} 2787 aa++; aj++; 2788 } 2789 } 2790 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2791 PetscFunctionReturn(0); 2792 } 2793 2794 #undef __FUNCT__ 2795 #define __FUNCT__ "MatGetRowMax_SeqAIJ" 2796 PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2797 { 2798 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2799 PetscErrorCode ierr; 2800 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2801 PetscScalar *x; 2802 MatScalar *aa; 2803 2804 PetscFunctionBegin; 2805 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2806 aa = a->a; 2807 ai = a->i; 2808 aj = a->j; 2809 2810 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2811 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2812 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 2813 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2814 for (i=0; i<m; i++) { 2815 ncols = ai[1] - ai[0]; ai++; 2816 if (ncols == A->cmap->n) { /* row is dense */ 2817 x[i] = *aa; if (idx) idx[i] = 0; 2818 } else { /* row is sparse so already KNOW maximum is 0.0 or higher */ 2819 x[i] = 0.0; 2820 if (idx) { 2821 idx[i] = 0; /* in case ncols is zero */ 2822 for (j=0;j<ncols;j++) { /* find first implicit 0.0 in the row */ 2823 if (aj[j] > j) { 2824 idx[i] = j; 2825 break; 2826 } 2827 } 2828 } 2829 } 2830 for (j=0; j<ncols; j++){ 2831 if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 2832 aa++; aj++; 2833 } 2834 } 2835 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2836 PetscFunctionReturn(0); 2837 } 2838 2839 #undef __FUNCT__ 2840 #define __FUNCT__ "MatGetRowMinAbs_SeqAIJ" 2841 PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2842 { 2843 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2844 PetscErrorCode ierr; 2845 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2846 PetscReal atmp; 2847 PetscScalar *x; 2848 MatScalar *aa; 2849 2850 PetscFunctionBegin; 2851 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2852 aa = a->a; 2853 ai = a->i; 2854 aj = a->j; 2855 2856 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2857 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2858 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 2859 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2860 for (i=0; i<m; i++) { 2861 ncols = ai[1] - ai[0]; ai++; 2862 if (ncols) { 2863 /* Get first nonzero */ 2864 for(j = 0; j < ncols; j++) { 2865 atmp = PetscAbsScalar(aa[j]); 2866 if (atmp > 1.0e-12) {x[i] = atmp; if (idx) idx[i] = aj[j]; break;} 2867 } 2868 if (j == ncols) {x[i] = *aa; if (idx) idx[i] = *aj;} 2869 } else { 2870 x[i] = 0.0; if (idx) idx[i] = 0; 2871 } 2872 for(j = 0; j < ncols; j++) { 2873 atmp = PetscAbsScalar(*aa); 2874 if (atmp > 1.0e-12 && PetscAbsScalar(x[i]) > atmp) {x[i] = atmp; if (idx) idx[i] = *aj;} 2875 aa++; aj++; 2876 } 2877 } 2878 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2879 PetscFunctionReturn(0); 2880 } 2881 2882 #undef __FUNCT__ 2883 #define __FUNCT__ "MatGetRowMin_SeqAIJ" 2884 PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2885 { 2886 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2887 PetscErrorCode ierr; 2888 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2889 PetscScalar *x; 2890 MatScalar *aa; 2891 2892 PetscFunctionBegin; 2893 if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2894 aa = a->a; 2895 ai = a->i; 2896 aj = a->j; 2897 2898 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2899 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2900 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 2901 if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2902 for (i=0; i<m; i++) { 2903 ncols = ai[1] - ai[0]; ai++; 2904 if (ncols == A->cmap->n) { /* row is dense */ 2905 x[i] = *aa; if (idx) idx[i] = 0; 2906 } else { /* row is sparse so already KNOW minimum is 0.0 or lower */ 2907 x[i] = 0.0; 2908 if (idx) { /* find first implicit 0.0 in the row */ 2909 idx[i] = 0; /* in case ncols is zero */ 2910 for (j=0;j<ncols;j++) { 2911 if (aj[j] > j) { 2912 idx[i] = j; 2913 break; 2914 } 2915 } 2916 } 2917 } 2918 for (j=0; j<ncols; j++){ 2919 if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 2920 aa++; aj++; 2921 } 2922 } 2923 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2924 PetscFunctionReturn(0); 2925 } 2926 2927 #include <petscblaslapack.h> 2928 #include <../src/mat/blockinvert.h> 2929 2930 #undef __FUNCT__ 2931 #define __FUNCT__ "MatInvertBlockDiagonal_SeqAIJ" 2932 PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,PetscScalar **values) 2933 { 2934 Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 2935 PetscErrorCode ierr; 2936 PetscInt i,bs = A->rmap->bs,mbs = A->rmap->n/A->rmap->bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j; 2937 MatScalar *diag,work[25],*v_work; 2938 PetscReal shift = 0.0; 2939 2940 PetscFunctionBegin; 2941 if (a->ibdiagvalid) { 2942 if (values) *values = a->ibdiag; 2943 PetscFunctionReturn(0); 2944 } 2945 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 2946 if (!a->ibdiag) { 2947 ierr = PetscMalloc(bs2*mbs*sizeof(PetscScalar),&a->ibdiag);CHKERRQ(ierr); 2948 ierr = PetscLogObjectMemory(A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr); 2949 } 2950 diag = a->ibdiag; 2951 if (values) *values = a->ibdiag; 2952 /* factor and invert each block */ 2953 switch (bs){ 2954 case 1: 2955 for (i=0; i<mbs; i++) { 2956 ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr); 2957 diag[i] = (PetscScalar)1.0 / (diag[i] + shift); 2958 } 2959 break; 2960 case 2: 2961 for (i=0; i<mbs; i++) { 2962 ij[0] = 2*i; ij[1] = 2*i + 1; 2963 ierr = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr); 2964 ierr = Kernel_A_gets_inverse_A_2(diag,shift);CHKERRQ(ierr); 2965 ierr = Kernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr); 2966 diag += 4; 2967 } 2968 break; 2969 case 3: 2970 for (i=0; i<mbs; i++) { 2971 ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2; 2972 ierr = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr); 2973 ierr = Kernel_A_gets_inverse_A_3(diag,shift);CHKERRQ(ierr); 2974 ierr = Kernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr); 2975 diag += 9; 2976 } 2977 break; 2978 case 4: 2979 for (i=0; i<mbs; i++) { 2980 ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3; 2981 ierr = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr); 2982 ierr = Kernel_A_gets_inverse_A_4(diag,shift);CHKERRQ(ierr); 2983 ierr = Kernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr); 2984 diag += 16; 2985 } 2986 break; 2987 case 5: 2988 for (i=0; i<mbs; i++) { 2989 ij[0] = 5*i; ij[1] = 5*i + 1; ij[2] = 5*i + 2; ij[3] = 5*i + 3; ij[4] = 5*i + 4; 2990 ierr = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr); 2991 ierr = Kernel_A_gets_inverse_A_5(diag,ipvt,work,shift);CHKERRQ(ierr); 2992 ierr = Kernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr); 2993 diag += 25; 2994 } 2995 break; 2996 case 6: 2997 for (i=0; i<mbs; i++) { 2998 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; 2999 ierr = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr); 3000 ierr = Kernel_A_gets_inverse_A_6(diag,shift);CHKERRQ(ierr); 3001 ierr = Kernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr); 3002 diag += 36; 3003 } 3004 break; 3005 case 7: 3006 for (i=0; i<mbs; i++) { 3007 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; 3008 ierr = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr); 3009 ierr = Kernel_A_gets_inverse_A_7(diag,shift);CHKERRQ(ierr); 3010 ierr = Kernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr); 3011 diag += 49; 3012 } 3013 break; 3014 default: 3015 ierr = PetscMalloc3(bs,MatScalar,&v_work,bs,PetscInt,&v_pivots,bs,PetscInt,&IJ);CHKERRQ(ierr); 3016 for (i=0; i<mbs; i++) { 3017 for (j=0; j<bs; j++) { 3018 IJ[j] = bs*i + j; 3019 } 3020 ierr = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr); 3021 ierr = Kernel_A_gets_inverse_A(bs,diag,v_pivots,v_work);CHKERRQ(ierr); 3022 ierr = Kernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr); 3023 diag += bs2; 3024 } 3025 ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr); 3026 } 3027 a->ibdiagvalid = PETSC_TRUE; 3028 PetscFunctionReturn(0); 3029 } 3030 3031 extern PetscErrorCode MatFDColoringApply_AIJ(Mat,MatFDColoring,Vec,MatStructure*,void*); 3032 /* -------------------------------------------------------------------*/ 3033 static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ, 3034 MatGetRow_SeqAIJ, 3035 MatRestoreRow_SeqAIJ, 3036 MatMult_SeqAIJ, 3037 /* 4*/ MatMultAdd_SeqAIJ, 3038 MatMultTranspose_SeqAIJ, 3039 MatMultTransposeAdd_SeqAIJ, 3040 0, 3041 0, 3042 0, 3043 /*10*/ 0, 3044 MatLUFactor_SeqAIJ, 3045 0, 3046 MatSOR_SeqAIJ, 3047 MatTranspose_SeqAIJ, 3048 /*15*/ MatGetInfo_SeqAIJ, 3049 MatEqual_SeqAIJ, 3050 MatGetDiagonal_SeqAIJ, 3051 MatDiagonalScale_SeqAIJ, 3052 MatNorm_SeqAIJ, 3053 /*20*/ 0, 3054 MatAssemblyEnd_SeqAIJ, 3055 MatSetOption_SeqAIJ, 3056 MatZeroEntries_SeqAIJ, 3057 /*24*/ MatZeroRows_SeqAIJ, 3058 0, 3059 0, 3060 0, 3061 0, 3062 /*29*/ MatSetUpPreallocation_SeqAIJ, 3063 0, 3064 0, 3065 MatGetArray_SeqAIJ, 3066 MatRestoreArray_SeqAIJ, 3067 /*34*/ MatDuplicate_SeqAIJ, 3068 0, 3069 0, 3070 MatILUFactor_SeqAIJ, 3071 0, 3072 /*39*/ MatAXPY_SeqAIJ, 3073 MatGetSubMatrices_SeqAIJ, 3074 MatIncreaseOverlap_SeqAIJ, 3075 MatGetValues_SeqAIJ, 3076 MatCopy_SeqAIJ, 3077 /*44*/ MatGetRowMax_SeqAIJ, 3078 MatScale_SeqAIJ, 3079 0, 3080 MatDiagonalSet_SeqAIJ, 3081 MatZeroRowsColumns_SeqAIJ, 3082 /*49*/ MatSetBlockSize_SeqAIJ, 3083 MatGetRowIJ_SeqAIJ, 3084 MatRestoreRowIJ_SeqAIJ, 3085 MatGetColumnIJ_SeqAIJ, 3086 MatRestoreColumnIJ_SeqAIJ, 3087 /*54*/ MatFDColoringCreate_SeqAIJ, 3088 0, 3089 0, 3090 MatPermute_SeqAIJ, 3091 0, 3092 /*59*/ 0, 3093 MatDestroy_SeqAIJ, 3094 MatView_SeqAIJ, 3095 0, 3096 0, 3097 /*64*/ 0, 3098 0, 3099 0, 3100 0, 3101 0, 3102 /*69*/ MatGetRowMaxAbs_SeqAIJ, 3103 MatGetRowMinAbs_SeqAIJ, 3104 0, 3105 MatSetColoring_SeqAIJ, 3106 #if defined(PETSC_HAVE_ADIC) 3107 MatSetValuesAdic_SeqAIJ, 3108 #else 3109 0, 3110 #endif 3111 /*74*/ MatSetValuesAdifor_SeqAIJ, 3112 MatFDColoringApply_AIJ, 3113 0, 3114 0, 3115 0, 3116 /*79*/ MatFindZeroDiagonals_SeqAIJ, 3117 0, 3118 0, 3119 0, 3120 MatLoad_SeqAIJ, 3121 /*84*/ MatIsSymmetric_SeqAIJ, 3122 MatIsHermitian_SeqAIJ, 3123 0, 3124 0, 3125 0, 3126 /*89*/ MatMatMult_SeqAIJ_SeqAIJ, 3127 MatMatMultSymbolic_SeqAIJ_SeqAIJ, 3128 MatMatMultNumeric_SeqAIJ_SeqAIJ, 3129 MatPtAP_Basic, 3130 MatPtAPSymbolic_SeqAIJ, 3131 /*94*/ MatPtAPNumeric_SeqAIJ, 3132 MatMatMultTranspose_SeqAIJ_SeqAIJ, 3133 MatMatMultTransposeSymbolic_SeqAIJ_SeqAIJ, 3134 MatMatMultTransposeNumeric_SeqAIJ_SeqAIJ, 3135 MatPtAPSymbolic_SeqAIJ_SeqAIJ, 3136 /*99*/ MatPtAPNumeric_SeqAIJ_SeqAIJ, 3137 0, 3138 0, 3139 MatConjugate_SeqAIJ, 3140 0, 3141 /*104*/MatSetValuesRow_SeqAIJ, 3142 MatRealPart_SeqAIJ, 3143 MatImaginaryPart_SeqAIJ, 3144 0, 3145 0, 3146 /*109*/MatMatSolve_SeqAIJ, 3147 0, 3148 MatGetRowMin_SeqAIJ, 3149 0, 3150 MatMissingDiagonal_SeqAIJ, 3151 /*114*/0, 3152 0, 3153 0, 3154 0, 3155 0, 3156 /*119*/0, 3157 0, 3158 0, 3159 0, 3160 MatGetMultiProcBlock_SeqAIJ, 3161 /*124*/MatFindNonzeroRows_SeqAIJ, 3162 MatGetColumnNorms_SeqAIJ, 3163 MatInvertBlockDiagonal_SeqAIJ, 3164 0, 3165 0, 3166 /*129*/0, 3167 MatMatTransposeMult_SeqAIJ_SeqAIJ, 3168 MatMatTransposeMultSymbolic_SeqAIJ_SeqAIJ, 3169 MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ, 3170 MatMultTransposeColoringCreate_SeqAIJ, 3171 /*134*/MatMultTransposeColoringApply_SeqAIJ 3172 }; 3173 3174 EXTERN_C_BEGIN 3175 #undef __FUNCT__ 3176 #define __FUNCT__ "MatSeqAIJSetColumnIndices_SeqAIJ" 3177 PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices) 3178 { 3179 Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3180 PetscInt i,nz,n; 3181 3182 PetscFunctionBegin; 3183 3184 nz = aij->maxnz; 3185 n = mat->rmap->n; 3186 for (i=0; i<nz; i++) { 3187 aij->j[i] = indices[i]; 3188 } 3189 aij->nz = nz; 3190 for (i=0; i<n; i++) { 3191 aij->ilen[i] = aij->imax[i]; 3192 } 3193 3194 PetscFunctionReturn(0); 3195 } 3196 EXTERN_C_END 3197 3198 #undef __FUNCT__ 3199 #define __FUNCT__ "MatSeqAIJSetColumnIndices" 3200 /*@ 3201 MatSeqAIJSetColumnIndices - Set the column indices for all the rows 3202 in the matrix. 3203 3204 Input Parameters: 3205 + mat - the SeqAIJ matrix 3206 - indices - the column indices 3207 3208 Level: advanced 3209 3210 Notes: 3211 This can be called if you have precomputed the nonzero structure of the 3212 matrix and want to provide it to the matrix object to improve the performance 3213 of the MatSetValues() operation. 3214 3215 You MUST have set the correct numbers of nonzeros per row in the call to 3216 MatCreateSeqAIJ(), and the columns indices MUST be sorted. 3217 3218 MUST be called before any calls to MatSetValues(); 3219 3220 The indices should start with zero, not one. 3221 3222 @*/ 3223 PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices) 3224 { 3225 PetscErrorCode ierr; 3226 3227 PetscFunctionBegin; 3228 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3229 PetscValidPointer(indices,2); 3230 ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt *),(mat,indices));CHKERRQ(ierr); 3231 PetscFunctionReturn(0); 3232 } 3233 3234 /* ----------------------------------------------------------------------------------------*/ 3235 3236 EXTERN_C_BEGIN 3237 #undef __FUNCT__ 3238 #define __FUNCT__ "MatStoreValues_SeqAIJ" 3239 PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) 3240 { 3241 Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3242 PetscErrorCode ierr; 3243 size_t nz = aij->i[mat->rmap->n]; 3244 3245 PetscFunctionBegin; 3246 if (aij->nonew != 1) { 3247 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3248 } 3249 3250 /* allocate space for values if not already there */ 3251 if (!aij->saved_values) { 3252 ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr); 3253 ierr = PetscLogObjectMemory(mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr); 3254 } 3255 3256 /* copy values over */ 3257 ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr); 3258 PetscFunctionReturn(0); 3259 } 3260 EXTERN_C_END 3261 3262 #undef __FUNCT__ 3263 #define __FUNCT__ "MatStoreValues" 3264 /*@ 3265 MatStoreValues - Stashes a copy of the matrix values; this allows, for 3266 example, reuse of the linear part of a Jacobian, while recomputing the 3267 nonlinear portion. 3268 3269 Collect on Mat 3270 3271 Input Parameters: 3272 . mat - the matrix (currently only AIJ matrices support this option) 3273 3274 Level: advanced 3275 3276 Common Usage, with SNESSolve(): 3277 $ Create Jacobian matrix 3278 $ Set linear terms into matrix 3279 $ Apply boundary conditions to matrix, at this time matrix must have 3280 $ final nonzero structure (i.e. setting the nonlinear terms and applying 3281 $ boundary conditions again will not change the nonzero structure 3282 $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3283 $ ierr = MatStoreValues(mat); 3284 $ Call SNESSetJacobian() with matrix 3285 $ In your Jacobian routine 3286 $ ierr = MatRetrieveValues(mat); 3287 $ Set nonlinear terms in matrix 3288 3289 Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself: 3290 $ // build linear portion of Jacobian 3291 $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3292 $ ierr = MatStoreValues(mat); 3293 $ loop over nonlinear iterations 3294 $ ierr = MatRetrieveValues(mat); 3295 $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian 3296 $ // call MatAssemblyBegin/End() on matrix 3297 $ Solve linear system with Jacobian 3298 $ endloop 3299 3300 Notes: 3301 Matrix must already be assemblied before calling this routine 3302 Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before 3303 calling this routine. 3304 3305 When this is called multiple times it overwrites the previous set of stored values 3306 and does not allocated additional space. 3307 3308 .seealso: MatRetrieveValues() 3309 3310 @*/ 3311 PetscErrorCode MatStoreValues(Mat mat) 3312 { 3313 PetscErrorCode ierr; 3314 3315 PetscFunctionBegin; 3316 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3317 if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 3318 if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3319 ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr); 3320 PetscFunctionReturn(0); 3321 } 3322 3323 EXTERN_C_BEGIN 3324 #undef __FUNCT__ 3325 #define __FUNCT__ "MatRetrieveValues_SeqAIJ" 3326 PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat) 3327 { 3328 Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 3329 PetscErrorCode ierr; 3330 PetscInt nz = aij->i[mat->rmap->n]; 3331 3332 PetscFunctionBegin; 3333 if (aij->nonew != 1) { 3334 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3335 } 3336 if (!aij->saved_values) { 3337 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first"); 3338 } 3339 /* copy values over */ 3340 ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr); 3341 PetscFunctionReturn(0); 3342 } 3343 EXTERN_C_END 3344 3345 #undef __FUNCT__ 3346 #define __FUNCT__ "MatRetrieveValues" 3347 /*@ 3348 MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 3349 example, reuse of the linear part of a Jacobian, while recomputing the 3350 nonlinear portion. 3351 3352 Collect on Mat 3353 3354 Input Parameters: 3355 . mat - the matrix (currently on AIJ matrices support this option) 3356 3357 Level: advanced 3358 3359 .seealso: MatStoreValues() 3360 3361 @*/ 3362 PetscErrorCode MatRetrieveValues(Mat mat) 3363 { 3364 PetscErrorCode ierr; 3365 3366 PetscFunctionBegin; 3367 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3368 if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 3369 if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3370 ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr); 3371 PetscFunctionReturn(0); 3372 } 3373 3374 3375 /* --------------------------------------------------------------------------------*/ 3376 #undef __FUNCT__ 3377 #define __FUNCT__ "MatCreateSeqAIJ" 3378 /*@C 3379 MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format 3380 (the default parallel PETSc format). For good matrix assembly performance 3381 the user should preallocate the matrix storage by setting the parameter nz 3382 (or the array nnz). By setting these parameters accurately, performance 3383 during matrix assembly can be increased by more than a factor of 50. 3384 3385 Collective on MPI_Comm 3386 3387 Input Parameters: 3388 + comm - MPI communicator, set to PETSC_COMM_SELF 3389 . m - number of rows 3390 . n - number of columns 3391 . nz - number of nonzeros per row (same for all rows) 3392 - nnz - array containing the number of nonzeros in the various rows 3393 (possibly different for each row) or PETSC_NULL 3394 3395 Output Parameter: 3396 . A - the matrix 3397 3398 It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 3399 MatXXXXSetPreallocation() paradgm instead of this routine directly. 3400 [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 3401 3402 Notes: 3403 If nnz is given then nz is ignored 3404 3405 The AIJ format (also called the Yale sparse matrix format or 3406 compressed row storage), is fully compatible with standard Fortran 77 3407 storage. That is, the stored row and column indices can begin at 3408 either one (as in Fortran) or zero. See the users' manual for details. 3409 3410 Specify the preallocated storage with either nz or nnz (not both). 3411 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 3412 allocation. For large problems you MUST preallocate memory or you 3413 will get TERRIBLE performance, see the users' manual chapter on matrices. 3414 3415 By default, this format uses inodes (identical nodes) when possible, to 3416 improve numerical efficiency of matrix-vector products and solves. We 3417 search for consecutive rows with the same nonzero structure, thereby 3418 reusing matrix information to achieve increased efficiency. 3419 3420 Options Database Keys: 3421 + -mat_no_inode - Do not use inodes 3422 - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3423 3424 Level: intermediate 3425 3426 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays() 3427 3428 @*/ 3429 PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A) 3430 { 3431 PetscErrorCode ierr; 3432 3433 PetscFunctionBegin; 3434 ierr = MatCreate(comm,A);CHKERRQ(ierr); 3435 ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr); 3436 ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr); 3437 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr); 3438 PetscFunctionReturn(0); 3439 } 3440 3441 #undef __FUNCT__ 3442 #define __FUNCT__ "MatSeqAIJSetPreallocation" 3443 /*@C 3444 MatSeqAIJSetPreallocation - For good matrix assembly performance 3445 the user should preallocate the matrix storage by setting the parameter nz 3446 (or the array nnz). By setting these parameters accurately, performance 3447 during matrix assembly can be increased by more than a factor of 50. 3448 3449 Collective on MPI_Comm 3450 3451 Input Parameters: 3452 + B - The matrix-free 3453 . nz - number of nonzeros per row (same for all rows) 3454 - nnz - array containing the number of nonzeros in the various rows 3455 (possibly different for each row) or PETSC_NULL 3456 3457 Notes: 3458 If nnz is given then nz is ignored 3459 3460 The AIJ format (also called the Yale sparse matrix format or 3461 compressed row storage), is fully compatible with standard Fortran 77 3462 storage. That is, the stored row and column indices can begin at 3463 either one (as in Fortran) or zero. See the users' manual for details. 3464 3465 Specify the preallocated storage with either nz or nnz (not both). 3466 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 3467 allocation. For large problems you MUST preallocate memory or you 3468 will get TERRIBLE performance, see the users' manual chapter on matrices. 3469 3470 You can call MatGetInfo() to get information on how effective the preallocation was; 3471 for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 3472 You can also run with the option -info and look for messages with the string 3473 malloc in them to see if additional memory allocation was needed. 3474 3475 Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix 3476 entries or columns indices 3477 3478 By default, this format uses inodes (identical nodes) when possible, to 3479 improve numerical efficiency of matrix-vector products and solves. We 3480 search for consecutive rows with the same nonzero structure, thereby 3481 reusing matrix information to achieve increased efficiency. 3482 3483 Options Database Keys: 3484 + -mat_no_inode - Do not use inodes 3485 . -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3486 - -mat_aij_oneindex - Internally use indexing starting at 1 3487 rather than 0. Note that when calling MatSetValues(), 3488 the user still MUST index entries starting at 0! 3489 3490 Level: intermediate 3491 3492 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo() 3493 3494 @*/ 3495 PetscErrorCode MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[]) 3496 { 3497 PetscErrorCode ierr; 3498 3499 PetscFunctionBegin; 3500 ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr); 3501 PetscFunctionReturn(0); 3502 } 3503 3504 EXTERN_C_BEGIN 3505 #undef __FUNCT__ 3506 #define __FUNCT__ "MatSeqAIJSetPreallocation_SeqAIJ" 3507 PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz) 3508 { 3509 Mat_SeqAIJ *b; 3510 PetscBool skipallocation = PETSC_FALSE; 3511 PetscErrorCode ierr; 3512 PetscInt i; 3513 3514 PetscFunctionBegin; 3515 3516 if (nz == MAT_SKIP_ALLOCATION) { 3517 skipallocation = PETSC_TRUE; 3518 nz = 0; 3519 } 3520 3521 ierr = PetscLayoutSetBlockSize(B->rmap,1);CHKERRQ(ierr); 3522 ierr = PetscLayoutSetBlockSize(B->cmap,1);CHKERRQ(ierr); 3523 ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 3524 ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 3525 3526 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 3527 if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz); 3528 if (nnz) { 3529 for (i=0; i<B->rmap->n; i++) { 3530 if (nnz[i] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]); 3531 if (nnz[i] > B->cmap->n) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %d value %d rowlength %d",i,nnz[i],B->cmap->n); 3532 } 3533 } 3534 3535 B->preallocated = PETSC_TRUE; 3536 b = (Mat_SeqAIJ*)B->data; 3537 3538 if (!skipallocation) { 3539 if (!b->imax) { 3540 ierr = PetscMalloc2(B->rmap->n,PetscInt,&b->imax,B->rmap->n,PetscInt,&b->ilen);CHKERRQ(ierr); 3541 ierr = PetscLogObjectMemory(B,2*B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 3542 } 3543 if (!nnz) { 3544 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 3545 else if (nz < 0) nz = 1; 3546 for (i=0; i<B->rmap->n; i++) b->imax[i] = nz; 3547 nz = nz*B->rmap->n; 3548 } else { 3549 nz = 0; 3550 for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz += nnz[i];} 3551 } 3552 /* b->ilen will count nonzeros in each row so far. */ 3553 for (i=0; i<B->rmap->n; i++) { b->ilen[i] = 0; } 3554 3555 /* allocate the matrix space */ 3556 ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr); 3557 ierr = PetscMalloc3(nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap->n+1,PetscInt,&b->i);CHKERRQ(ierr); 3558 ierr = PetscLogObjectMemory(B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr); 3559 b->i[0] = 0; 3560 for (i=1; i<B->rmap->n+1; i++) { 3561 b->i[i] = b->i[i-1] + b->imax[i-1]; 3562 } 3563 b->singlemalloc = PETSC_TRUE; 3564 b->free_a = PETSC_TRUE; 3565 b->free_ij = PETSC_TRUE; 3566 } else { 3567 b->free_a = PETSC_FALSE; 3568 b->free_ij = PETSC_FALSE; 3569 } 3570 3571 b->nz = 0; 3572 b->maxnz = nz; 3573 B->info.nz_unneeded = (double)b->maxnz; 3574 PetscFunctionReturn(0); 3575 } 3576 EXTERN_C_END 3577 3578 #undef __FUNCT__ 3579 #define __FUNCT__ "MatSeqAIJSetPreallocationCSR" 3580 /*@ 3581 MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format. 3582 3583 Input Parameters: 3584 + B - the matrix 3585 . i - the indices into j for the start of each row (starts with zero) 3586 . j - the column indices for each row (starts with zero) these must be sorted for each row 3587 - v - optional values in the matrix 3588 3589 Level: developer 3590 3591 The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays() 3592 3593 .keywords: matrix, aij, compressed row, sparse, sequential 3594 3595 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), SeqAIJ 3596 @*/ 3597 PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[]) 3598 { 3599 PetscErrorCode ierr; 3600 3601 PetscFunctionBegin; 3602 PetscValidHeaderSpecific(B,MAT_CLASSID,1); 3603 ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr); 3604 PetscFunctionReturn(0); 3605 } 3606 3607 EXTERN_C_BEGIN 3608 #undef __FUNCT__ 3609 #define __FUNCT__ "MatSeqAIJSetPreallocationCSR_SeqAIJ" 3610 PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[]) 3611 { 3612 PetscInt i; 3613 PetscInt m,n; 3614 PetscInt nz; 3615 PetscInt *nnz, nz_max = 0; 3616 PetscScalar *values; 3617 PetscErrorCode ierr; 3618 3619 PetscFunctionBegin; 3620 ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr); 3621 3622 if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]); 3623 ierr = PetscMalloc((m+1) * sizeof(PetscInt), &nnz);CHKERRQ(ierr); 3624 for(i = 0; i < m; i++) { 3625 nz = Ii[i+1]- Ii[i]; 3626 nz_max = PetscMax(nz_max, nz); 3627 if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz); 3628 nnz[i] = nz; 3629 } 3630 ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr); 3631 ierr = PetscFree(nnz);CHKERRQ(ierr); 3632 3633 if (v) { 3634 values = (PetscScalar*) v; 3635 } else { 3636 ierr = PetscMalloc(nz_max*sizeof(PetscScalar), &values);CHKERRQ(ierr); 3637 ierr = PetscMemzero(values, nz_max*sizeof(PetscScalar));CHKERRQ(ierr); 3638 } 3639 3640 for(i = 0; i < m; i++) { 3641 nz = Ii[i+1] - Ii[i]; 3642 ierr = MatSetValues_SeqAIJ(B, 1, &i, nz, J+Ii[i], values + (v ? Ii[i] : 0), INSERT_VALUES);CHKERRQ(ierr); 3643 } 3644 3645 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3646 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3647 3648 if (!v) { 3649 ierr = PetscFree(values);CHKERRQ(ierr); 3650 } 3651 PetscFunctionReturn(0); 3652 } 3653 EXTERN_C_END 3654 3655 #include <../src/mat/impls/dense/seq/dense.h> 3656 #include <private/petscaxpy.h> 3657 3658 #undef __FUNCT__ 3659 #define __FUNCT__ "MatMatMultNumeric_SeqDense_SeqAIJ" 3660 /* 3661 Computes (B'*A')' since computing B*A directly is untenable 3662 3663 n p p 3664 ( ) ( ) ( ) 3665 m ( A ) * n ( B ) = m ( C ) 3666 ( ) ( ) ( ) 3667 3668 */ 3669 PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C) 3670 { 3671 PetscErrorCode ierr; 3672 Mat_SeqDense *sub_a = (Mat_SeqDense*)A->data; 3673 Mat_SeqAIJ *sub_b = (Mat_SeqAIJ*)B->data; 3674 Mat_SeqDense *sub_c = (Mat_SeqDense*)C->data; 3675 PetscInt i,n,m,q,p; 3676 const PetscInt *ii,*idx; 3677 const PetscScalar *b,*a,*a_q; 3678 PetscScalar *c,*c_q; 3679 3680 PetscFunctionBegin; 3681 m = A->rmap->n; 3682 n = A->cmap->n; 3683 p = B->cmap->n; 3684 a = sub_a->v; 3685 b = sub_b->a; 3686 c = sub_c->v; 3687 ierr = PetscMemzero(c,m*p*sizeof(PetscScalar));CHKERRQ(ierr); 3688 3689 ii = sub_b->i; 3690 idx = sub_b->j; 3691 for (i=0; i<n; i++) { 3692 q = ii[i+1] - ii[i]; 3693 while (q-->0) { 3694 c_q = c + m*(*idx); 3695 a_q = a + m*i; 3696 PetscAXPY(c_q,*b,a_q,m); 3697 idx++; 3698 b++; 3699 } 3700 } 3701 PetscFunctionReturn(0); 3702 } 3703 3704 #undef __FUNCT__ 3705 #define __FUNCT__ "MatMatMultSymbolic_SeqDense_SeqAIJ" 3706 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat *C) 3707 { 3708 PetscErrorCode ierr; 3709 PetscInt m=A->rmap->n,n=B->cmap->n; 3710 Mat Cmat; 3711 3712 PetscFunctionBegin; 3713 if (A->cmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %d != B->rmap->n %d\n",A->cmap->n,B->rmap->n); 3714 ierr = MatCreate(((PetscObject)A)->comm,&Cmat);CHKERRQ(ierr); 3715 ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr); 3716 ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr); 3717 ierr = MatSeqDenseSetPreallocation(Cmat,PETSC_NULL);CHKERRQ(ierr); 3718 Cmat->assembled = PETSC_TRUE; 3719 *C = Cmat; 3720 PetscFunctionReturn(0); 3721 } 3722 3723 /* ----------------------------------------------------------------*/ 3724 #undef __FUNCT__ 3725 #define __FUNCT__ "MatMatMult_SeqDense_SeqAIJ" 3726 PetscErrorCode MatMatMult_SeqDense_SeqAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 3727 { 3728 PetscErrorCode ierr; 3729 3730 PetscFunctionBegin; 3731 if (scall == MAT_INITIAL_MATRIX){ 3732 ierr = MatMatMultSymbolic_SeqDense_SeqAIJ(A,B,fill,C);CHKERRQ(ierr); 3733 } 3734 ierr = MatMatMultNumeric_SeqDense_SeqAIJ(A,B,*C);CHKERRQ(ierr); 3735 PetscFunctionReturn(0); 3736 } 3737 3738 3739 /*MC 3740 MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 3741 based on compressed sparse row format. 3742 3743 Options Database Keys: 3744 . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 3745 3746 Level: beginner 3747 3748 .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType 3749 M*/ 3750 3751 EXTERN_C_BEGIN 3752 #if defined(PETSC_HAVE_PASTIX) 3753 extern PetscErrorCode MatGetFactor_seqaij_pastix(Mat,MatFactorType,Mat*); 3754 #endif 3755 #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) 3756 extern PetscErrorCode MatGetFactor_seqaij_essl(Mat,MatFactorType,Mat *); 3757 #endif 3758 extern PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*); 3759 extern PetscErrorCode MatGetFactor_seqaij_petsc(Mat,MatFactorType,Mat*); 3760 extern PetscErrorCode MatGetFactor_seqaij_bas(Mat,MatFactorType,Mat*); 3761 extern PetscErrorCode MatGetFactorAvailable_seqaij_petsc(Mat,MatFactorType,PetscBool *); 3762 #if defined(PETSC_HAVE_MUMPS) 3763 extern PetscErrorCode MatGetFactor_aij_mumps(Mat,MatFactorType,Mat*); 3764 #endif 3765 #if defined(PETSC_HAVE_SUPERLU) 3766 extern PetscErrorCode MatGetFactor_seqaij_superlu(Mat,MatFactorType,Mat*); 3767 #endif 3768 #if defined(PETSC_HAVE_SUPERLU_DIST) 3769 extern PetscErrorCode MatGetFactor_seqaij_superlu_dist(Mat,MatFactorType,Mat*); 3770 #endif 3771 #if defined(PETSC_HAVE_SPOOLES) 3772 extern PetscErrorCode MatGetFactor_seqaij_spooles(Mat,MatFactorType,Mat*); 3773 #endif 3774 #if defined(PETSC_HAVE_UMFPACK) 3775 extern PetscErrorCode MatGetFactor_seqaij_umfpack(Mat,MatFactorType,Mat*); 3776 #endif 3777 #if defined(PETSC_HAVE_CHOLMOD) 3778 extern PetscErrorCode MatGetFactor_seqaij_cholmod(Mat,MatFactorType,Mat*); 3779 #endif 3780 #if defined(PETSC_HAVE_LUSOL) 3781 extern PetscErrorCode MatGetFactor_seqaij_lusol(Mat,MatFactorType,Mat*); 3782 #endif 3783 #if defined(PETSC_HAVE_MATLAB_ENGINE) 3784 extern PetscErrorCode MatGetFactor_seqaij_matlab(Mat,MatFactorType,Mat*); 3785 extern PetscErrorCode MatlabEnginePut_SeqAIJ(PetscObject,void*); 3786 extern PetscErrorCode MatlabEngineGet_SeqAIJ(PetscObject,void*); 3787 #endif 3788 EXTERN_C_END 3789 3790 EXTERN_C_BEGIN 3791 #undef __FUNCT__ 3792 #define __FUNCT__ "MatCreate_SeqAIJ" 3793 PetscErrorCode MatCreate_SeqAIJ(Mat B) 3794 { 3795 Mat_SeqAIJ *b; 3796 PetscErrorCode ierr; 3797 PetscMPIInt size; 3798 3799 PetscFunctionBegin; 3800 ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr); 3801 if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1"); 3802 3803 ierr = PetscNewLog(B,Mat_SeqAIJ,&b);CHKERRQ(ierr); 3804 B->data = (void*)b; 3805 ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 3806 b->row = 0; 3807 b->col = 0; 3808 b->icol = 0; 3809 b->reallocs = 0; 3810 b->ignorezeroentries = PETSC_FALSE; 3811 b->roworiented = PETSC_TRUE; 3812 b->nonew = 0; 3813 b->diag = 0; 3814 b->solve_work = 0; 3815 B->spptr = 0; 3816 b->saved_values = 0; 3817 b->idiag = 0; 3818 b->mdiag = 0; 3819 b->ssor_work = 0; 3820 b->omega = 1.0; 3821 b->fshift = 0.0; 3822 b->idiagvalid = PETSC_FALSE; 3823 b->ibdiagvalid = PETSC_FALSE; 3824 b->keepnonzeropattern = PETSC_FALSE; 3825 b->xtoy = 0; 3826 b->XtoY = 0; 3827 B->same_nonzero = PETSC_FALSE; 3828 3829 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 3830 #if defined(PETSC_HAVE_MATLAB_ENGINE) 3831 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_matlab_C","MatGetFactor_seqaij_matlab",MatGetFactor_seqaij_matlab);CHKERRQ(ierr); 3832 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEnginePut_C","MatlabEnginePut_SeqAIJ",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr); 3833 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEngineGet_C","MatlabEngineGet_SeqAIJ",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr); 3834 #endif 3835 #if defined(PETSC_HAVE_PASTIX) 3836 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_pastix_C","MatGetFactor_seqaij_pastix",MatGetFactor_seqaij_pastix);CHKERRQ(ierr); 3837 #endif 3838 #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) 3839 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_essl_C","MatGetFactor_seqaij_essl",MatGetFactor_seqaij_essl);CHKERRQ(ierr); 3840 #endif 3841 #if defined(PETSC_HAVE_SUPERLU) 3842 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_C","MatGetFactor_seqaij_superlu",MatGetFactor_seqaij_superlu);CHKERRQ(ierr); 3843 #endif 3844 #if defined(PETSC_HAVE_SUPERLU_DIST) 3845 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_dist_C","MatGetFactor_seqaij_superlu_dist",MatGetFactor_seqaij_superlu_dist);CHKERRQ(ierr); 3846 #endif 3847 #if defined(PETSC_HAVE_SPOOLES) 3848 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_spooles_C","MatGetFactor_seqaij_spooles",MatGetFactor_seqaij_spooles);CHKERRQ(ierr); 3849 #endif 3850 #if defined(PETSC_HAVE_MUMPS) 3851 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_mumps_C","MatGetFactor_aij_mumps",MatGetFactor_aij_mumps);CHKERRQ(ierr); 3852 #endif 3853 #if defined(PETSC_HAVE_UMFPACK) 3854 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_umfpack_C","MatGetFactor_seqaij_umfpack",MatGetFactor_seqaij_umfpack);CHKERRQ(ierr); 3855 #endif 3856 #if defined(PETSC_HAVE_CHOLMOD) 3857 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_cholmod_C","MatGetFactor_seqaij_cholmod",MatGetFactor_seqaij_cholmod);CHKERRQ(ierr); 3858 #endif 3859 #if defined(PETSC_HAVE_LUSOL) 3860 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_lusol_C","MatGetFactor_seqaij_lusol",MatGetFactor_seqaij_lusol);CHKERRQ(ierr); 3861 #endif 3862 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_petsc_C","MatGetFactor_seqaij_petsc",MatGetFactor_seqaij_petsc);CHKERRQ(ierr); 3863 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_petsc_C","MatGetFactorAvailable_seqaij_petsc",MatGetFactorAvailable_seqaij_petsc);CHKERRQ(ierr); 3864 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_bas_C","MatGetFactor_seqaij_bas",MatGetFactor_seqaij_bas);CHKERRQ(ierr); 3865 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C","MatSeqAIJSetColumnIndices_SeqAIJ",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr); 3866 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C","MatStoreValues_SeqAIJ",MatStoreValues_SeqAIJ);CHKERRQ(ierr); 3867 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C","MatRetrieveValues_SeqAIJ",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr); 3868 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqsbaij_C","MatConvert_SeqAIJ_SeqSBAIJ",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr); 3869 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqbaij_C","MatConvert_SeqAIJ_SeqBAIJ",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr); 3870 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqaijperm_C","MatConvert_SeqAIJ_SeqAIJPERM",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr); 3871 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C","MatConvert_SeqAIJ_SeqAIJCRL",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr); 3872 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C","MatIsTranspose_SeqAIJ",MatIsTranspose_SeqAIJ);CHKERRQ(ierr); 3873 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsHermitianTranspose_C","MatIsHermitianTranspose_SeqAIJ",MatIsTranspose_SeqAIJ);CHKERRQ(ierr); 3874 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocation_C","MatSeqAIJSetPreallocation_SeqAIJ",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr); 3875 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C","MatSeqAIJSetPreallocationCSR_SeqAIJ",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr); 3876 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatReorderForNonzeroDiagonal_C","MatReorderForNonzeroDiagonal_SeqAIJ",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr); 3877 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMult_seqdense_seqaij_C","MatMatMult_SeqDense_SeqAIJ",MatMatMult_SeqDense_SeqAIJ);CHKERRQ(ierr); 3878 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaij_C","MatMatMultSymbolic_SeqDense_SeqAIJ",MatMatMultSymbolic_SeqDense_SeqAIJ);CHKERRQ(ierr); 3879 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultNumeric_seqdense_seqaij_C","MatMatMultNumeric_SeqDense_SeqAIJ",MatMatMultNumeric_SeqDense_SeqAIJ);CHKERRQ(ierr); 3880 ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr); 3881 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 3882 PetscFunctionReturn(0); 3883 } 3884 EXTERN_C_END 3885 3886 #if defined(PETSC_HAVE_PTHREADCLASSES) 3887 EXTERN_C_BEGIN 3888 #undef __FUNCT__ 3889 #define __FUNCT__ "MatCreate_SeqAIJPThread" 3890 PetscErrorCode MatCreate_SeqAIJPThread(Mat B) 3891 { 3892 PetscErrorCode ierr; 3893 3894 PetscFunctionBegin; 3895 ierr = MatCreate_SeqAIJ(B); 3896 ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 3897 B->ops->mult = MatMult_SeqAIJPThread; 3898 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJPTHREAD);CHKERRQ(ierr); 3899 PetscFunctionReturn(0); 3900 } 3901 EXTERN_C_END 3902 #endif 3903 3904 #undef __FUNCT__ 3905 #define __FUNCT__ "MatDuplicateNoCreate_SeqAIJ" 3906 /* 3907 Given a matrix generated with MatGetFactor() duplicates all the information in A into B 3908 */ 3909 PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace) 3910 { 3911 Mat_SeqAIJ *c,*a = (Mat_SeqAIJ*)A->data; 3912 PetscErrorCode ierr; 3913 PetscInt i,m = A->rmap->n; 3914 3915 PetscFunctionBegin; 3916 c = (Mat_SeqAIJ*)C->data; 3917 3918 C->factortype = A->factortype; 3919 c->row = 0; 3920 c->col = 0; 3921 c->icol = 0; 3922 c->reallocs = 0; 3923 3924 C->assembled = PETSC_TRUE; 3925 3926 ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr); 3927 ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr); 3928 3929 ierr = PetscMalloc2(m,PetscInt,&c->imax,m,PetscInt,&c->ilen);CHKERRQ(ierr); 3930 ierr = PetscLogObjectMemory(C, 2*m*sizeof(PetscInt));CHKERRQ(ierr); 3931 for (i=0; i<m; i++) { 3932 c->imax[i] = a->imax[i]; 3933 c->ilen[i] = a->ilen[i]; 3934 } 3935 3936 /* allocate the matrix space */ 3937 if (mallocmatspace){ 3938 ierr = PetscMalloc3(a->i[m],PetscScalar,&c->a,a->i[m],PetscInt,&c->j,m+1,PetscInt,&c->i);CHKERRQ(ierr); 3939 ierr = PetscLogObjectMemory(C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 3940 c->singlemalloc = PETSC_TRUE; 3941 ierr = PetscMemcpy(c->i,a->i,(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 3942 if (m > 0) { 3943 ierr = PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(PetscInt));CHKERRQ(ierr); 3944 if (cpvalues == MAT_COPY_VALUES) { 3945 ierr = PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr); 3946 } else { 3947 ierr = PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr); 3948 } 3949 } 3950 } 3951 3952 c->ignorezeroentries = a->ignorezeroentries; 3953 c->roworiented = a->roworiented; 3954 c->nonew = a->nonew; 3955 if (a->diag) { 3956 ierr = PetscMalloc((m+1)*sizeof(PetscInt),&c->diag);CHKERRQ(ierr); 3957 ierr = PetscLogObjectMemory(C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 3958 for (i=0; i<m; i++) { 3959 c->diag[i] = a->diag[i]; 3960 } 3961 } else c->diag = 0; 3962 c->solve_work = 0; 3963 c->saved_values = 0; 3964 c->idiag = 0; 3965 c->ssor_work = 0; 3966 c->keepnonzeropattern = a->keepnonzeropattern; 3967 c->free_a = PETSC_TRUE; 3968 c->free_ij = PETSC_TRUE; 3969 c->xtoy = 0; 3970 c->XtoY = 0; 3971 3972 c->nz = a->nz; 3973 c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 3974 C->preallocated = PETSC_TRUE; 3975 3976 c->compressedrow.use = a->compressedrow.use; 3977 c->compressedrow.nrows = a->compressedrow.nrows; 3978 c->compressedrow.check = a->compressedrow.check; 3979 if (a->compressedrow.use){ 3980 i = a->compressedrow.nrows; 3981 ierr = PetscMalloc2(i+1,PetscInt,&c->compressedrow.i,i,PetscInt,&c->compressedrow.rindex);CHKERRQ(ierr); 3982 ierr = PetscMemcpy(c->compressedrow.i,a->compressedrow.i,(i+1)*sizeof(PetscInt));CHKERRQ(ierr); 3983 ierr = PetscMemcpy(c->compressedrow.rindex,a->compressedrow.rindex,i*sizeof(PetscInt));CHKERRQ(ierr); 3984 } else { 3985 c->compressedrow.use = PETSC_FALSE; 3986 c->compressedrow.i = PETSC_NULL; 3987 c->compressedrow.rindex = PETSC_NULL; 3988 } 3989 C->same_nonzero = A->same_nonzero; 3990 ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr); 3991 3992 ierr = PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr); 3993 PetscFunctionReturn(0); 3994 } 3995 3996 #undef __FUNCT__ 3997 #define __FUNCT__ "MatDuplicate_SeqAIJ" 3998 PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B) 3999 { 4000 PetscErrorCode ierr; 4001 4002 PetscFunctionBegin; 4003 ierr = MatCreate(((PetscObject)A)->comm,B);CHKERRQ(ierr); 4004 ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr); 4005 ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr); 4006 ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr); 4007 PetscFunctionReturn(0); 4008 } 4009 4010 #undef __FUNCT__ 4011 #define __FUNCT__ "MatLoad_SeqAIJ" 4012 PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer) 4013 { 4014 Mat_SeqAIJ *a; 4015 PetscErrorCode ierr; 4016 PetscInt i,sum,nz,header[4],*rowlengths = 0,M,N,rows,cols; 4017 int fd; 4018 PetscMPIInt size; 4019 MPI_Comm comm; 4020 PetscInt bs = 1; 4021 4022 PetscFunctionBegin; 4023 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 4024 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 4025 if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"view must have one processor"); 4026 4027 ierr = PetscOptionsBegin(comm,PETSC_NULL,"Options for loading SEQAIJ matrix","Mat");CHKERRQ(ierr); 4028 ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,PETSC_NULL);CHKERRQ(ierr); 4029 ierr = PetscOptionsEnd();CHKERRQ(ierr); 4030 4031 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 4032 ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr); 4033 if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file"); 4034 M = header[1]; N = header[2]; nz = header[3]; 4035 4036 if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ"); 4037 4038 /* read in row lengths */ 4039 ierr = PetscMalloc(M*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr); 4040 ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr); 4041 4042 /* check if sum of rowlengths is same as nz */ 4043 for (i=0,sum=0; i< M; i++) sum +=rowlengths[i]; 4044 if (sum != nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Inconsistant matrix data in file. no-nonzeros = %d, sum-row-lengths = %d\n",nz,sum); 4045 4046 /* set global size if not set already*/ 4047 if (newMat->rmap->n < 0 && newMat->rmap->N < 0 && newMat->cmap->n < 0 && newMat->cmap->N < 0) { 4048 ierr = MatSetSizes(newMat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 4049 } else { 4050 /* if sizes and type are already set, check if the vector global sizes are correct */ 4051 ierr = MatGetSize(newMat,&rows,&cols);CHKERRQ(ierr); 4052 if (rows < 0 && cols < 0){ /* user might provide local size instead of global size */ 4053 ierr = MatGetLocalSize(newMat,&rows,&cols);CHKERRQ(ierr); 4054 } 4055 if (M != rows || N != cols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%d, %d) than the input matrix (%d, %d)",M,N,rows,cols); 4056 } 4057 ierr = MatSeqAIJSetPreallocation_SeqAIJ(newMat,0,rowlengths);CHKERRQ(ierr); 4058 a = (Mat_SeqAIJ*)newMat->data; 4059 4060 ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT);CHKERRQ(ierr); 4061 4062 /* read in nonzero values */ 4063 ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);CHKERRQ(ierr); 4064 4065 /* set matrix "i" values */ 4066 a->i[0] = 0; 4067 for (i=1; i<= M; i++) { 4068 a->i[i] = a->i[i-1] + rowlengths[i-1]; 4069 a->ilen[i-1] = rowlengths[i-1]; 4070 } 4071 ierr = PetscFree(rowlengths);CHKERRQ(ierr); 4072 4073 ierr = MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4074 ierr = MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4075 if (bs > 1) {ierr = MatSetBlockSize(newMat,bs);CHKERRQ(ierr);} 4076 PetscFunctionReturn(0); 4077 } 4078 4079 #undef __FUNCT__ 4080 #define __FUNCT__ "MatEqual_SeqAIJ" 4081 PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg) 4082 { 4083 Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data; 4084 PetscErrorCode ierr; 4085 #if defined(PETSC_USE_COMPLEX) 4086 PetscInt k; 4087 #endif 4088 4089 PetscFunctionBegin; 4090 /* If the matrix dimensions are not equal,or no of nonzeros */ 4091 if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) { 4092 *flg = PETSC_FALSE; 4093 PetscFunctionReturn(0); 4094 } 4095 4096 /* if the a->i are the same */ 4097 ierr = PetscMemcmp(a->i,b->i,(A->rmap->n+1)*sizeof(PetscInt),flg);CHKERRQ(ierr); 4098 if (!*flg) PetscFunctionReturn(0); 4099 4100 /* if a->j are the same */ 4101 ierr = PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),flg);CHKERRQ(ierr); 4102 if (!*flg) PetscFunctionReturn(0); 4103 4104 /* if a->a are the same */ 4105 #if defined(PETSC_USE_COMPLEX) 4106 for (k=0; k<a->nz; k++){ 4107 if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])){ 4108 *flg = PETSC_FALSE; 4109 PetscFunctionReturn(0); 4110 } 4111 } 4112 #else 4113 ierr = PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);CHKERRQ(ierr); 4114 #endif 4115 PetscFunctionReturn(0); 4116 } 4117 4118 #undef __FUNCT__ 4119 #define __FUNCT__ "MatCreateSeqAIJWithArrays" 4120 /*@ 4121 MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format) 4122 provided by the user. 4123 4124 Collective on MPI_Comm 4125 4126 Input Parameters: 4127 + comm - must be an MPI communicator of size 1 4128 . m - number of rows 4129 . n - number of columns 4130 . i - row indices 4131 . j - column indices 4132 - a - matrix values 4133 4134 Output Parameter: 4135 . mat - the matrix 4136 4137 Level: intermediate 4138 4139 Notes: 4140 The i, j, and a arrays are not copied by this routine, the user must free these arrays 4141 once the matrix is destroyed and not before 4142 4143 You cannot set new nonzero locations into this matrix, that will generate an error. 4144 4145 The i and j indices are 0 based 4146 4147 The format which is used for the sparse matrix input, is equivalent to a 4148 row-major ordering.. i.e for the following matrix, the input data expected is 4149 as shown: 4150 4151 1 0 0 4152 2 0 3 4153 4 5 6 4154 4155 i = {0,1,3,6} [size = nrow+1 = 3+1] 4156 j = {0,0,2,0,1,2} [size = nz = 6]; values must be sorted for each row 4157 v = {1,2,3,4,5,6} [size = nz = 6] 4158 4159 4160 .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR() 4161 4162 @*/ 4163 PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat) 4164 { 4165 PetscErrorCode ierr; 4166 PetscInt ii; 4167 Mat_SeqAIJ *aij; 4168 #if defined(PETSC_USE_DEBUG) 4169 PetscInt jj; 4170 #endif 4171 4172 PetscFunctionBegin; 4173 if (i[0]) { 4174 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 4175 } 4176 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 4177 ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr); 4178 ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr); 4179 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr); 4180 aij = (Mat_SeqAIJ*)(*mat)->data; 4181 ierr = PetscMalloc2(m,PetscInt,&aij->imax,m,PetscInt,&aij->ilen);CHKERRQ(ierr); 4182 4183 aij->i = i; 4184 aij->j = j; 4185 aij->a = a; 4186 aij->singlemalloc = PETSC_FALSE; 4187 aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 4188 aij->free_a = PETSC_FALSE; 4189 aij->free_ij = PETSC_FALSE; 4190 4191 for (ii=0; ii<m; ii++) { 4192 aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii]; 4193 #if defined(PETSC_USE_DEBUG) 4194 if (i[ii+1] - i[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %d length = %d",ii,i[ii+1] - i[ii]); 4195 for (jj=i[ii]+1; jj<i[ii+1]; jj++) { 4196 if (j[jj] < j[jj-1]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual colum %D) in row %D is not sorted",jj-i[ii],j[jj],ii); 4197 if (j[jj] == j[jj]-1) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual colum %D) in row %D is identical to previous entry",jj-i[ii],j[jj],ii); 4198 } 4199 #endif 4200 } 4201 #if defined(PETSC_USE_DEBUG) 4202 for (ii=0; ii<aij->i[m]; ii++) { 4203 if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]); 4204 if (j[ii] > n - 1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]); 4205 } 4206 #endif 4207 4208 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4209 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4210 PetscFunctionReturn(0); 4211 } 4212 #undef __FUNCT__ 4213 #define __FUNCT__ "MatCreateSeqAIJFromTriple" 4214 /*@C 4215 MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format) 4216 provided by the user. 4217 4218 Collective on MPI_Comm 4219 4220 Input Parameters: 4221 + comm - must be an MPI communicator of size 1 4222 . m - number of rows 4223 . n - number of columns 4224 . i - row indices 4225 . j - column indices 4226 . a - matrix values 4227 . nz - number of nonzeros 4228 - idx - 0 or 1 based 4229 4230 Output Parameter: 4231 . mat - the matrix 4232 4233 Level: intermediate 4234 4235 Notes: 4236 The i and j indices are 0 based 4237 4238 The format which is used for the sparse matrix input, is equivalent to a 4239 row-major ordering.. i.e for the following matrix, the input data expected is 4240 as shown: 4241 4242 1 0 0 4243 2 0 3 4244 4 5 6 4245 4246 i = {0,1,1,2,2,2} 4247 j = {0,0,2,0,1,2} 4248 v = {1,2,3,4,5,6} 4249 4250 4251 .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR() 4252 4253 @*/ 4254 PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat,PetscInt nz,PetscBool idx) 4255 { 4256 PetscErrorCode ierr; 4257 PetscInt ii, *nnz, one = 1,row,col; 4258 4259 4260 PetscFunctionBegin; 4261 ierr = PetscMalloc(m*sizeof(PetscInt),&nnz);CHKERRQ(ierr); 4262 ierr = PetscMemzero(nnz,m*sizeof(PetscInt));CHKERRQ(ierr); 4263 for (ii = 0; ii < nz; ii++){ 4264 nnz[i[ii]] += 1; 4265 } 4266 //ierr = MatSeqAIJCreate(comm,m,n,0,nnz,mat);CHKERRQ(ierr); 4267 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 4268 ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr); 4269 ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr); 4270 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr); 4271 for (ii = 0; ii < nz; ii++){ 4272 if (idx){ 4273 row = i[ii] - 1; 4274 col = j[ii] - 1; 4275 } else { 4276 row = i[ii]; 4277 col = j[ii]; 4278 } 4279 ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr); 4280 } 4281 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4282 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4283 ierr = PetscFree(nnz);CHKERRQ(ierr); 4284 PetscFunctionReturn(0); 4285 } 4286 4287 #undef __FUNCT__ 4288 #define __FUNCT__ "MatSetColoring_SeqAIJ" 4289 PetscErrorCode MatSetColoring_SeqAIJ(Mat A,ISColoring coloring) 4290 { 4291 PetscErrorCode ierr; 4292 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 4293 4294 PetscFunctionBegin; 4295 if (coloring->ctype == IS_COLORING_GLOBAL) { 4296 ierr = ISColoringReference(coloring);CHKERRQ(ierr); 4297 a->coloring = coloring; 4298 } else if (coloring->ctype == IS_COLORING_GHOSTED) { 4299 PetscInt i,*larray; 4300 ISColoring ocoloring; 4301 ISColoringValue *colors; 4302 4303 /* set coloring for diagonal portion */ 4304 ierr = PetscMalloc(A->cmap->n*sizeof(PetscInt),&larray);CHKERRQ(ierr); 4305 for (i=0; i<A->cmap->n; i++) { 4306 larray[i] = i; 4307 } 4308 ierr = ISGlobalToLocalMappingApply(A->cmap->mapping,IS_GTOLM_MASK,A->cmap->n,larray,PETSC_NULL,larray);CHKERRQ(ierr); 4309 ierr = PetscMalloc(A->cmap->n*sizeof(ISColoringValue),&colors);CHKERRQ(ierr); 4310 for (i=0; i<A->cmap->n; i++) { 4311 colors[i] = coloring->colors[larray[i]]; 4312 } 4313 ierr = PetscFree(larray);CHKERRQ(ierr); 4314 ierr = ISColoringCreate(PETSC_COMM_SELF,coloring->n,A->cmap->n,colors,&ocoloring);CHKERRQ(ierr); 4315 a->coloring = ocoloring; 4316 } 4317 PetscFunctionReturn(0); 4318 } 4319 4320 #if defined(PETSC_HAVE_ADIC) 4321 EXTERN_C_BEGIN 4322 #include <adic/ad_utils.h> 4323 EXTERN_C_END 4324 4325 #undef __FUNCT__ 4326 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ" 4327 PetscErrorCode MatSetValuesAdic_SeqAIJ(Mat A,void *advalues) 4328 { 4329 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 4330 PetscInt m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j,nlen; 4331 PetscScalar *v = a->a,*values = ((PetscScalar*)advalues)+1; 4332 ISColoringValue *color; 4333 4334 PetscFunctionBegin; 4335 if (!a->coloring) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix"); 4336 nlen = PetscADGetDerivTypeSize()/sizeof(PetscScalar); 4337 color = a->coloring->colors; 4338 /* loop over rows */ 4339 for (i=0; i<m; i++) { 4340 nz = ii[i+1] - ii[i]; 4341 /* loop over columns putting computed value into matrix */ 4342 for (j=0; j<nz; j++) { 4343 *v++ = values[color[*jj++]]; 4344 } 4345 values += nlen; /* jump to next row of derivatives */ 4346 } 4347 PetscFunctionReturn(0); 4348 } 4349 #endif 4350 4351 #undef __FUNCT__ 4352 #define __FUNCT__ "MatSetValuesAdifor_SeqAIJ" 4353 PetscErrorCode MatSetValuesAdifor_SeqAIJ(Mat A,PetscInt nl,void *advalues) 4354 { 4355 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 4356 PetscInt m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j; 4357 MatScalar *v = a->a; 4358 PetscScalar *values = (PetscScalar *)advalues; 4359 ISColoringValue *color; 4360 4361 PetscFunctionBegin; 4362 if (!a->coloring) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix"); 4363 color = a->coloring->colors; 4364 /* loop over rows */ 4365 for (i=0; i<m; i++) { 4366 nz = ii[i+1] - ii[i]; 4367 /* loop over columns putting computed value into matrix */ 4368 for (j=0; j<nz; j++) { 4369 *v++ = values[color[*jj++]]; 4370 } 4371 values += nl; /* jump to next row of derivatives */ 4372 } 4373 PetscFunctionReturn(0); 4374 } 4375 4376 /* 4377 Special version for direct calls from Fortran 4378 */ 4379 #include <private/fortranimpl.h> 4380 #if defined(PETSC_HAVE_FORTRAN_CAPS) 4381 #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ 4382 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 4383 #define matsetvaluesseqaij_ matsetvaluesseqaij 4384 #endif 4385 4386 /* Change these macros so can be used in void function */ 4387 #undef CHKERRQ 4388 #define CHKERRQ(ierr) CHKERRABORT(((PetscObject)A)->comm,ierr) 4389 #undef SETERRQ2 4390 #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr) 4391 4392 EXTERN_C_BEGIN 4393 #undef __FUNCT__ 4394 #define __FUNCT__ "matsetvaluesseqaij_" 4395 void PETSC_STDCALL matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr) 4396 { 4397 Mat A = *AA; 4398 PetscInt m = *mm, n = *nn; 4399 InsertMode is = *isis; 4400 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 4401 PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N; 4402 PetscInt *imax,*ai,*ailen; 4403 PetscErrorCode ierr; 4404 PetscInt *aj,nonew = a->nonew,lastcol = -1; 4405 MatScalar *ap,value,*aa; 4406 PetscBool ignorezeroentries = a->ignorezeroentries; 4407 PetscBool roworiented = a->roworiented; 4408 4409 PetscFunctionBegin; 4410 ierr = MatPreallocated(A);CHKERRQ(ierr); 4411 imax = a->imax; 4412 ai = a->i; 4413 ailen = a->ilen; 4414 aj = a->j; 4415 aa = a->a; 4416 4417 for (k=0; k<m; k++) { /* loop over added rows */ 4418 row = im[k]; 4419 if (row < 0) continue; 4420 #if defined(PETSC_USE_DEBUG) 4421 if (row >= A->rmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large"); 4422 #endif 4423 rp = aj + ai[row]; ap = aa + ai[row]; 4424 rmax = imax[row]; nrow = ailen[row]; 4425 low = 0; 4426 high = nrow; 4427 for (l=0; l<n; l++) { /* loop over added columns */ 4428 if (in[l] < 0) continue; 4429 #if defined(PETSC_USE_DEBUG) 4430 if (in[l] >= A->cmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Column too large"); 4431 #endif 4432 col = in[l]; 4433 if (roworiented) { 4434 value = v[l + k*n]; 4435 } else { 4436 value = v[k + l*m]; 4437 } 4438 if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 4439 4440 if (col <= lastcol) low = 0; else high = nrow; 4441 lastcol = col; 4442 while (high-low > 5) { 4443 t = (low+high)/2; 4444 if (rp[t] > col) high = t; 4445 else low = t; 4446 } 4447 for (i=low; i<high; i++) { 4448 if (rp[i] > col) break; 4449 if (rp[i] == col) { 4450 if (is == ADD_VALUES) ap[i] += value; 4451 else ap[i] = value; 4452 goto noinsert; 4453 } 4454 } 4455 if (value == 0.0 && ignorezeroentries) goto noinsert; 4456 if (nonew == 1) goto noinsert; 4457 if (nonew == -1) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix"); 4458 MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar); 4459 N = nrow++ - 1; a->nz++; high++; 4460 /* shift up all the later entries in this row */ 4461 for (ii=N; ii>=i; ii--) { 4462 rp[ii+1] = rp[ii]; 4463 ap[ii+1] = ap[ii]; 4464 } 4465 rp[i] = col; 4466 ap[i] = value; 4467 noinsert:; 4468 low = i + 1; 4469 } 4470 ailen[row] = nrow; 4471 } 4472 A->same_nonzero = PETSC_FALSE; 4473 PetscFunctionReturnVoid(); 4474 } 4475 EXTERN_C_END 4476 4477