1 #ifdef PETSC_RCS_HEADER 2 static char vcid[] = "$Id: aij.c,v 1.260 1998/04/15 22:50:57 curfman Exp balay $"; 3 #endif 4 5 /* 6 Defines the basic matrix operations for the AIJ (compressed row) 7 matrix storage format. 8 */ 9 10 #include "pinclude/pviewer.h" 11 #include "sys.h" 12 #include "src/mat/impls/aij/seq/aij.h" 13 #include "src/vec/vecimpl.h" 14 #include "src/inline/spops.h" 15 #include "src/inline/dot.h" 16 #include "src/inline/bitarray.h" 17 18 /* 19 Basic AIJ format ILU based on drop tolerance 20 */ 21 #undef __FUNC__ 22 #define __FUNC__ "MatILUDTFactor_SeqAIJ" 23 int MatILUDTFactor_SeqAIJ(Mat A,double dt,int maxnz,IS row,IS col,Mat *fact) 24 { 25 /* Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; */ 26 int ierr = 1; 27 28 PetscFunctionBegin; 29 SETERRQ(ierr,0,"Not implemented"); 30 #if !defined(USE_PETSC_DEBUG) 31 PetscFunctionReturn(0); 32 #endif 33 } 34 35 extern int MatToSymmetricIJ_SeqAIJ(int,int*,int*,int,int,int**,int**); 36 37 #undef __FUNC__ 38 #define __FUNC__ "MatGetRowIJ_SeqAIJ" 39 int MatGetRowIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *m,int **ia,int **ja, 40 PetscTruth *done) 41 { 42 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 43 int ierr,i,ishift; 44 45 PetscFunctionBegin; 46 *m = A->m; 47 if (!ia) PetscFunctionReturn(0); 48 ishift = a->indexshift; 49 if (symmetric) { 50 ierr = MatToSymmetricIJ_SeqAIJ(a->m,a->i,a->j,ishift,oshift,ia,ja); CHKERRQ(ierr); 51 } else if (oshift == 0 && ishift == -1) { 52 int nz = a->i[a->m]; 53 /* malloc space and subtract 1 from i and j indices */ 54 *ia = (int *) PetscMalloc( (a->m+1)*sizeof(int) ); CHKPTRQ(*ia); 55 *ja = (int *) PetscMalloc( (nz+1)*sizeof(int) ); CHKPTRQ(*ja); 56 for ( i=0; i<nz; i++ ) (*ja)[i] = a->j[i] - 1; 57 for ( i=0; i<a->m+1; i++ ) (*ia)[i] = a->i[i] - 1; 58 } else if (oshift == 1 && ishift == 0) { 59 int nz = a->i[a->m] + 1; 60 /* malloc space and add 1 to i and j indices */ 61 *ia = (int *) PetscMalloc( (a->m+1)*sizeof(int) ); CHKPTRQ(*ia); 62 *ja = (int *) PetscMalloc( (nz+1)*sizeof(int) ); CHKPTRQ(*ja); 63 for ( i=0; i<nz; i++ ) (*ja)[i] = a->j[i] + 1; 64 for ( i=0; i<a->m+1; i++ ) (*ia)[i] = a->i[i] + 1; 65 } else { 66 *ia = a->i; *ja = a->j; 67 } 68 69 PetscFunctionReturn(0); 70 } 71 72 #undef __FUNC__ 73 #define __FUNC__ "MatRestoreRowIJ_SeqAIJ" 74 int MatRestoreRowIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *n,int **ia,int **ja, 75 PetscTruth *done) 76 { 77 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 78 int ishift = a->indexshift; 79 80 PetscFunctionBegin; 81 if (!ia) PetscFunctionReturn(0); 82 if (symmetric || (oshift == 0 && ishift == -1) || (oshift == 1 && ishift == 0)) { 83 PetscFree(*ia); 84 PetscFree(*ja); 85 } 86 PetscFunctionReturn(0); 87 } 88 89 #undef __FUNC__ 90 #define __FUNC__ "MatGetColumnIJ_SeqAIJ" 91 int MatGetColumnIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *nn,int **ia,int **ja, 92 PetscTruth *done) 93 { 94 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 95 int ierr,i,ishift = a->indexshift,*collengths,*cia,*cja,n = A->n,m = A->m; 96 int nz = a->i[m]+ishift,row,*jj,mr,col; 97 98 PetscFunctionBegin; 99 *nn = A->n; 100 if (!ia) PetscFunctionReturn(0); 101 if (symmetric) { 102 ierr = MatToSymmetricIJ_SeqAIJ(a->m,a->i,a->j,ishift,oshift,ia,ja); CHKERRQ(ierr); 103 } else { 104 collengths = (int *) PetscMalloc( (n+1)*sizeof(int) ); CHKPTRQ(collengths); 105 PetscMemzero(collengths,n*sizeof(int)); 106 cia = (int *) PetscMalloc( (n+1)*sizeof(int) ); CHKPTRQ(cia); 107 cja = (int *) PetscMalloc( (nz+1)*sizeof(int) ); CHKPTRQ(cja); 108 jj = a->j; 109 for ( i=0; i<nz; i++ ) { 110 collengths[jj[i] + ishift]++; 111 } 112 cia[0] = oshift; 113 for ( i=0; i<n; i++) { 114 cia[i+1] = cia[i] + collengths[i]; 115 } 116 PetscMemzero(collengths,n*sizeof(int)); 117 jj = a->j; 118 for ( row=0; row<m; row++ ) { 119 mr = a->i[row+1] - a->i[row]; 120 for ( i=0; i<mr; i++ ) { 121 col = *jj++ + ishift; 122 cja[cia[col] + collengths[col]++ - oshift] = row + oshift; 123 } 124 } 125 PetscFree(collengths); 126 *ia = cia; *ja = cja; 127 } 128 129 PetscFunctionReturn(0); 130 } 131 132 #undef __FUNC__ 133 #define __FUNC__ "MatRestoreColumnIJ_SeqAIJ" 134 int MatRestoreColumnIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *n,int **ia, 135 int **ja,PetscTruth *done) 136 { 137 PetscFunctionBegin; 138 if (!ia) PetscFunctionReturn(0); 139 140 PetscFree(*ia); 141 PetscFree(*ja); 142 143 PetscFunctionReturn(0); 144 } 145 146 #define CHUNKSIZE 15 147 148 #undef __FUNC__ 149 #define __FUNC__ "MatSetValues_SeqAIJ" 150 int MatSetValues_SeqAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v,InsertMode is) 151 { 152 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 153 int *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax, N, sorted = a->sorted; 154 int *imax = a->imax, *ai = a->i, *ailen = a->ilen,roworiented = a->roworiented; 155 int *aj = a->j, nonew = a->nonew,shift = a->indexshift; 156 Scalar *ap,value, *aa = a->a; 157 158 PetscFunctionBegin; 159 for ( k=0; k<m; k++ ) { /* loop over added rows */ 160 row = im[k]; 161 #if defined(USE_PETSC_BOPT_g) 162 if (row < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative row"); 163 if (row >= a->m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large"); 164 #endif 165 rp = aj + ai[row] + shift; ap = aa + ai[row] + shift; 166 rmax = imax[row]; nrow = ailen[row]; 167 low = 0; 168 for ( l=0; l<n; l++ ) { /* loop over added columns */ 169 #if defined(USE_PETSC_BOPT_g) 170 if (in[l] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative column"); 171 if (in[l] >= a->n) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Column too large"); 172 #endif 173 col = in[l] - shift; 174 if (roworiented) { 175 value = *v++; 176 } 177 else { 178 value = v[k + l*m]; 179 } 180 if (!sorted) low = 0; high = nrow; 181 while (high-low > 5) { 182 t = (low+high)/2; 183 if (rp[t] > col) high = t; 184 else low = t; 185 } 186 for ( i=low; i<high; i++ ) { 187 if (rp[i] > col) break; 188 if (rp[i] == col) { 189 if (is == ADD_VALUES) ap[i] += value; 190 else ap[i] = value; 191 goto noinsert; 192 } 193 } 194 if (nonew == 1) goto noinsert; 195 else if (nonew == -1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Inserting a new nonzero in the matrix"); 196 if (nrow >= rmax) { 197 /* there is no extra room in row, therefore enlarge */ 198 int new_nz = ai[a->m] + CHUNKSIZE,len,*new_i,*new_j; 199 Scalar *new_a; 200 201 if (nonew == -2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Inserting a new nonzero in the matrix"); 202 203 /* malloc new storage space */ 204 len = new_nz*(sizeof(int)+sizeof(Scalar))+(a->m+1)*sizeof(int); 205 new_a = (Scalar *) PetscMalloc( len ); CHKPTRQ(new_a); 206 new_j = (int *) (new_a + new_nz); 207 new_i = new_j + new_nz; 208 209 /* copy over old data into new slots */ 210 for ( ii=0; ii<row+1; ii++ ) {new_i[ii] = ai[ii];} 211 for ( ii=row+1; ii<a->m+1; ii++ ) {new_i[ii] = ai[ii]+CHUNKSIZE;} 212 PetscMemcpy(new_j,aj,(ai[row]+nrow+shift)*sizeof(int)); 213 len = (new_nz - CHUNKSIZE - ai[row] - nrow - shift); 214 PetscMemcpy(new_j+ai[row]+shift+nrow+CHUNKSIZE,aj+ai[row]+shift+nrow, 215 len*sizeof(int)); 216 PetscMemcpy(new_a,aa,(ai[row]+nrow+shift)*sizeof(Scalar)); 217 PetscMemcpy(new_a+ai[row]+shift+nrow+CHUNKSIZE,aa+ai[row]+shift+nrow, 218 len*sizeof(Scalar)); 219 /* free up old matrix storage */ 220 PetscFree(a->a); 221 if (!a->singlemalloc) {PetscFree(a->i);PetscFree(a->j);} 222 aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j; 223 a->singlemalloc = 1; 224 225 rp = aj + ai[row] + shift; ap = aa + ai[row] + shift; 226 rmax = imax[row] = imax[row] + CHUNKSIZE; 227 PLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + sizeof(Scalar))); 228 a->maxnz += CHUNKSIZE; 229 a->reallocs++; 230 } 231 N = nrow++ - 1; a->nz++; 232 /* shift up all the later entries in this row */ 233 for ( ii=N; ii>=i; ii-- ) { 234 rp[ii+1] = rp[ii]; 235 ap[ii+1] = ap[ii]; 236 } 237 rp[i] = col; 238 ap[i] = value; 239 noinsert:; 240 low = i + 1; 241 } 242 ailen[row] = nrow; 243 } 244 PetscFunctionReturn(0); 245 } 246 247 #undef __FUNC__ 248 #define __FUNC__ "MatGetValues_SeqAIJ" 249 int MatGetValues_SeqAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v) 250 { 251 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 252 int *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j; 253 int *ai = a->i, *ailen = a->ilen, shift = a->indexshift; 254 Scalar *ap, *aa = a->a, zero = 0.0; 255 256 PetscFunctionBegin; 257 for ( k=0; k<m; k++ ) { /* loop over rows */ 258 row = im[k]; 259 if (row < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative row"); 260 if (row >= a->m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large"); 261 rp = aj + ai[row] + shift; ap = aa + ai[row] + shift; 262 nrow = ailen[row]; 263 for ( l=0; l<n; l++ ) { /* loop over columns */ 264 if (in[l] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative column"); 265 if (in[l] >= a->n) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Column too large"); 266 col = in[l] - shift; 267 high = nrow; low = 0; /* assume unsorted */ 268 while (high-low > 5) { 269 t = (low+high)/2; 270 if (rp[t] > col) high = t; 271 else low = t; 272 } 273 for ( i=low; i<high; i++ ) { 274 if (rp[i] > col) break; 275 if (rp[i] == col) { 276 *v++ = ap[i]; 277 goto finished; 278 } 279 } 280 *v++ = zero; 281 finished:; 282 } 283 } 284 PetscFunctionReturn(0); 285 } 286 287 288 #undef __FUNC__ 289 #define __FUNC__ "MatView_SeqAIJ_Binary" 290 extern int MatView_SeqAIJ_Binary(Mat A,Viewer viewer) 291 { 292 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 293 int i, fd, *col_lens, ierr; 294 295 PetscFunctionBegin; 296 ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr); 297 col_lens = (int *) PetscMalloc( (4+a->m)*sizeof(int) ); CHKPTRQ(col_lens); 298 col_lens[0] = MAT_COOKIE; 299 col_lens[1] = a->m; 300 col_lens[2] = a->n; 301 col_lens[3] = a->nz; 302 303 /* store lengths of each row and write (including header) to file */ 304 for ( i=0; i<a->m; i++ ) { 305 col_lens[4+i] = a->i[i+1] - a->i[i]; 306 } 307 ierr = PetscBinaryWrite(fd,col_lens,4+a->m,PETSC_INT,1); CHKERRQ(ierr); 308 PetscFree(col_lens); 309 310 /* store column indices (zero start index) */ 311 if (a->indexshift) { 312 for ( i=0; i<a->nz; i++ ) a->j[i]--; 313 } 314 ierr = PetscBinaryWrite(fd,a->j,a->nz,PETSC_INT,0); CHKERRQ(ierr); 315 if (a->indexshift) { 316 for ( i=0; i<a->nz; i++ ) a->j[i]++; 317 } 318 319 /* store nonzero values */ 320 ierr = PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,0); CHKERRQ(ierr); 321 PetscFunctionReturn(0); 322 } 323 324 #undef __FUNC__ 325 #define __FUNC__ "MatView_SeqAIJ_ASCII" 326 extern int MatView_SeqAIJ_ASCII(Mat A,Viewer viewer) 327 { 328 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 329 int ierr, i,j, m = a->m, shift = a->indexshift, format, flg1,flg2; 330 FILE *fd; 331 char *outputname; 332 333 PetscFunctionBegin; 334 ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr); 335 ierr = ViewerFileGetOutputname_Private(viewer,&outputname); CHKERRQ(ierr); 336 ierr = ViewerGetFormat(viewer,&format); 337 if (format == VIEWER_FORMAT_ASCII_INFO) { 338 PetscFunctionReturn(0); 339 } else if (format == VIEWER_FORMAT_ASCII_INFO_LONG) { 340 ierr = OptionsHasName(PETSC_NULL,"-mat_aij_no_inode",&flg1); CHKERRQ(ierr); 341 ierr = OptionsHasName(PETSC_NULL,"-mat_no_unroll",&flg2); CHKERRQ(ierr); 342 if (flg1 || flg2) fprintf(fd," not using I-node routines\n"); 343 else fprintf(fd," using I-node routines: found %d nodes, limit used is %d\n", 344 a->inode.node_count,a->inode.limit); 345 } else if (format == VIEWER_FORMAT_ASCII_MATLAB) { 346 int nofinalvalue = 0; 347 if ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != a->n-!shift)) { 348 nofinalvalue = 1; 349 } 350 fprintf(fd,"%% Size = %d %d \n",m,a->n); 351 fprintf(fd,"%% Nonzeros = %d \n",a->nz); 352 fprintf(fd,"zzz = zeros(%d,3);\n",a->nz+nofinalvalue); 353 fprintf(fd,"zzz = [\n"); 354 355 for (i=0; i<m; i++) { 356 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 357 #if defined(USE_PETSC_COMPLEX) 358 fprintf(fd,"%d %d %18.16e + %18.16e i \n",i+1,a->j[j]+!shift,real(a->a[j]),imag(a->a[j])); 359 #else 360 fprintf(fd,"%d %d %18.16e\n", i+1, a->j[j]+!shift, a->a[j]); 361 #endif 362 } 363 } 364 if (nofinalvalue) { 365 fprintf(fd,"%d %d %18.16e\n", m, a->n, 0.0); 366 } 367 fprintf(fd,"];\n %s = spconvert(zzz);\n",outputname); 368 } else if (format == VIEWER_FORMAT_ASCII_COMMON) { 369 for ( i=0; i<m; i++ ) { 370 fprintf(fd,"row %d:",i); 371 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 372 #if defined(USE_PETSC_COMPLEX) 373 if (imag(a->a[j]) > 0.0 && real(a->a[j]) != 0.0) 374 fprintf(fd," %d %g + %g i",a->j[j]+shift,real(a->a[j]),imag(a->a[j])); 375 else if (imag(a->a[j]) < 0.0 && real(a->a[j]) != 0.0) 376 fprintf(fd," %d %g - %g i",a->j[j]+shift,real(a->a[j]),-imag(a->a[j])); 377 else if (real(a->a[j]) != 0.0) 378 fprintf(fd," %d %g ",a->j[j]+shift,real(a->a[j])); 379 #else 380 if (a->a[j] != 0.0) fprintf(fd," %d %g ",a->j[j]+shift,a->a[j]); 381 #endif 382 } 383 fprintf(fd,"\n"); 384 } 385 } 386 else if (format == VIEWER_FORMAT_ASCII_SYMMODU) { 387 int nzd=0, fshift=1, *sptr; 388 sptr = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(sptr); 389 for ( i=0; i<m; i++ ) { 390 sptr[i] = nzd+1; 391 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 392 if (a->j[j] >= i) { 393 #if defined(USE_PETSC_COMPLEX) 394 if (imag(a->a[j]) != 0.0 || real(a->a[j]) != 0.0) nzd++; 395 #else 396 if (a->a[j] != 0.0) nzd++; 397 #endif 398 } 399 } 400 } 401 sptr[m] = nzd+1; 402 fprintf(fd," %d %d\n\n",m,nzd); 403 for ( i=0; i<m+1; i+=6 ) { 404 if (i+4<m) fprintf(fd," %d %d %d %d %d %d\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4],sptr[i+5]); 405 else if (i+3<m) fprintf(fd," %d %d %d %d %d\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4]); 406 else if (i+2<m) fprintf(fd," %d %d %d %d\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]); 407 else if (i+1<m) fprintf(fd," %d %d %d\n",sptr[i],sptr[i+1],sptr[i+2]); 408 else if (i<m) fprintf(fd," %d %d\n",sptr[i],sptr[i+1]); 409 else fprintf(fd," %d\n",sptr[i]); 410 } 411 fprintf(fd,"\n"); 412 PetscFree(sptr); 413 for ( i=0; i<m; i++ ) { 414 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 415 if (a->j[j] >= i) fprintf(fd," %d ",a->j[j]+fshift); 416 } 417 fprintf(fd,"\n"); 418 } 419 fprintf(fd,"\n"); 420 for ( i=0; i<m; i++ ) { 421 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 422 if (a->j[j] >= i) { 423 #if defined(USE_PETSC_COMPLEX) 424 if (imag(a->a[j]) != 0.0 || real(a->a[j]) != 0.0) 425 fprintf(fd," %18.16e %18.16e ",real(a->a[j]),imag(a->a[j])); 426 #else 427 if (a->a[j] != 0.0) fprintf(fd," %18.16e ",a->a[j]); 428 #endif 429 } 430 } 431 fprintf(fd,"\n"); 432 } 433 } else { 434 for ( i=0; i<m; i++ ) { 435 fprintf(fd,"row %d:",i); 436 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 437 #if defined(USE_PETSC_COMPLEX) 438 if (imag(a->a[j]) > 0.0) { 439 fprintf(fd," %d %g + %g i",a->j[j]+shift,real(a->a[j]),imag(a->a[j])); 440 } else if (imag(a->a[j]) < 0.0) { 441 fprintf(fd," %d %g - %g i",a->j[j]+shift,real(a->a[j]),-imag(a->a[j])); 442 } else { 443 fprintf(fd," %d %g ",a->j[j]+shift,real(a->a[j])); 444 } 445 #else 446 fprintf(fd," %d %g ",a->j[j]+shift,a->a[j]); 447 #endif 448 } 449 fprintf(fd,"\n"); 450 } 451 } 452 fflush(fd); 453 PetscFunctionReturn(0); 454 } 455 456 #undef __FUNC__ 457 #define __FUNC__ "MatView_SeqAIJ_Draw" 458 extern int MatView_SeqAIJ_Draw(Mat A,Viewer viewer) 459 { 460 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 461 int ierr, i,j, m = a->m, shift = a->indexshift,pause,color; 462 int format; 463 double xl,yl,xr,yr,w,h,xc,yc,scale = 1.0,x_l,x_r,y_l,y_r,maxv = 0.0; 464 Draw draw; 465 DrawButton button; 466 PetscTruth isnull; 467 468 PetscFunctionBegin; 469 ierr = ViewerDrawGetDraw(viewer,&draw); CHKERRQ(ierr); 470 ierr = DrawSynchronizedClear(draw); CHKERRQ(ierr); 471 ierr = ViewerGetFormat(viewer,&format); CHKERRQ(ierr); 472 ierr = DrawIsNull(draw,&isnull); CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); 473 474 xr = a->n; yr = a->m; h = yr/10.0; w = xr/10.0; 475 xr += w; yr += h; xl = -w; yl = -h; 476 ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr); 477 /* loop over matrix elements drawing boxes */ 478 479 if (format != VIEWER_FORMAT_DRAW_CONTOUR) { 480 /* Blue for negative, Cyan for zero and Red for positive */ 481 color = DRAW_BLUE; 482 for ( i=0; i<m; i++ ) { 483 y_l = m - i - 1.0; y_r = y_l + 1.0; 484 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 485 x_l = a->j[j] + shift; x_r = x_l + 1.0; 486 #if defined(USE_PETSC_COMPLEX) 487 if (real(a->a[j]) >= 0.) continue; 488 #else 489 if (a->a[j] >= 0.) continue; 490 #endif 491 DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color); 492 } 493 } 494 color = DRAW_CYAN; 495 for ( i=0; i<m; i++ ) { 496 y_l = m - i - 1.0; y_r = y_l + 1.0; 497 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 498 x_l = a->j[j] + shift; x_r = x_l + 1.0; 499 if (a->a[j] != 0.) continue; 500 DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color); 501 } 502 } 503 color = DRAW_RED; 504 for ( i=0; i<m; i++ ) { 505 y_l = m - i - 1.0; y_r = y_l + 1.0; 506 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 507 x_l = a->j[j] + shift; x_r = x_l + 1.0; 508 #if defined(USE_PETSC_COMPLEX) 509 if (real(a->a[j]) <= 0.) continue; 510 #else 511 if (a->a[j] <= 0.) continue; 512 #endif 513 DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color); 514 } 515 } 516 } else { 517 /* use contour shading to indicate magnitude of values */ 518 /* first determine max of all nonzero values */ 519 int nz = a->nz,count; 520 Draw popup; 521 522 for ( i=0; i<nz; i++ ) { 523 if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]); 524 } 525 ierr = DrawGetPopup(draw,&popup); CHKERRQ(ierr); 526 ierr = DrawScalePopup(popup,0.0,maxv); CHKERRQ(ierr); 527 count = 0; 528 for ( i=0; i<m; i++ ) { 529 y_l = m - i - 1.0; y_r = y_l + 1.0; 530 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 531 x_l = a->j[j] + shift; x_r = x_l + 1.0; 532 color = 32 + (int) ((200.0 - 32.0)*PetscAbsScalar(a->a[count])/maxv); 533 DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color); 534 count++; 535 } 536 } 537 } 538 DrawSynchronizedFlush(draw); 539 DrawGetPause(draw,&pause); 540 if (pause >= 0) { PetscSleep(pause); PetscFunctionReturn(0);} 541 542 /* allow the matrix to zoom or shrink */ 543 ierr = DrawCheckResizedWindow(draw); 544 ierr = DrawSynchronizedGetMouseButton(draw,&button,&xc,&yc,0,0); 545 while (button != BUTTON_RIGHT) { 546 DrawSynchronizedClear(draw); 547 if (button == BUTTON_LEFT) scale = .5; 548 else if (button == BUTTON_CENTER) scale = 2.; 549 xl = scale*(xl + w - xc) + xc - w*scale; 550 xr = scale*(xr - w - xc) + xc + w*scale; 551 yl = scale*(yl + h - yc) + yc - h*scale; 552 yr = scale*(yr - h - yc) + yc + h*scale; 553 w *= scale; h *= scale; 554 ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr); 555 if (format != VIEWER_FORMAT_DRAW_CONTOUR) { 556 /* Blue for negative, Cyan for zero and Red for positive */ 557 color = DRAW_BLUE; 558 for ( i=0; i<m; i++ ) { 559 y_l = m - i - 1.0; y_r = y_l + 1.0; 560 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 561 x_l = a->j[j] + shift; x_r = x_l + 1.0; 562 #if defined(USE_PETSC_COMPLEX) 563 if (real(a->a[j]) >= 0.) continue; 564 #else 565 if (a->a[j] >= 0.) continue; 566 #endif 567 DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color); 568 } 569 } 570 color = DRAW_CYAN; 571 for ( i=0; i<m; i++ ) { 572 y_l = m - i - 1.0; y_r = y_l + 1.0; 573 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 574 x_l = a->j[j] + shift; x_r = x_l + 1.0; 575 if (a->a[j] != 0.) continue; 576 DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color); 577 } 578 } 579 color = DRAW_RED; 580 for ( i=0; i<m; i++ ) { 581 y_l = m - i - 1.0; y_r = y_l + 1.0; 582 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 583 x_l = a->j[j] + shift; x_r = x_l + 1.0; 584 #if defined(USE_PETSC_COMPLEX) 585 if (real(a->a[j]) <= 0.) continue; 586 #else 587 if (a->a[j] <= 0.) continue; 588 #endif 589 DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color); 590 } 591 } 592 } else { 593 /* use contour shading to indicate magnitude of values */ 594 int count = 0; 595 for ( i=0; i<m; i++ ) { 596 y_l = m - i - 1.0; y_r = y_l + 1.0; 597 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 598 x_l = a->j[j] + shift; x_r = x_l + 1.0; 599 color = 32 + (int) ((200.0 - 32.0)*PetscAbsScalar(a->a[count])/maxv); 600 DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color); CHKERRQ(ierr); 601 count++; 602 } 603 } 604 } 605 606 ierr = DrawCheckResizedWindow(draw); CHKERRQ(ierr); 607 ierr = DrawSynchronizedGetMouseButton(draw,&button,&xc,&yc,0,0); CHKERRQ(ierr); 608 } 609 PetscFunctionReturn(0); 610 } 611 612 #undef __FUNC__ 613 #define __FUNC__ "MatView_SeqAIJ" 614 int MatView_SeqAIJ(Mat A,Viewer viewer) 615 { 616 Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 617 ViewerType vtype; 618 int ierr; 619 620 PetscFunctionBegin; 621 ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr); 622 if (vtype == MATLAB_VIEWER) { 623 ierr = ViewerMatlabPutSparse_Private(viewer,a->m,a->n,a->nz,a->a,a->i,a->j); CHKERRQ(ierr); 624 } else if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER){ 625 ierr = MatView_SeqAIJ_ASCII(A,viewer); CHKERRQ(ierr); 626 } else if (vtype == BINARY_FILE_VIEWER) { 627 ierr = MatView_SeqAIJ_Binary(A,viewer); CHKERRQ(ierr); 628 } else if (vtype == DRAW_VIEWER) { 629 ierr = MatView_SeqAIJ_Draw(A,viewer); CHKERRQ(ierr); 630 } else { 631 SETERRQ(1,1,"Viewer type not supported by PETSc object"); 632 } 633 PetscFunctionReturn(0); 634 } 635 636 extern int Mat_AIJ_CheckInode(Mat); 637 #undef __FUNC__ 638 #define __FUNC__ "MatAssemblyEnd_SeqAIJ" 639 int MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode) 640 { 641 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 642 int fshift = 0,i,j,*ai = a->i, *aj = a->j, *imax = a->imax,ierr; 643 int m = a->m, *ip, N, *ailen = a->ilen,shift = a->indexshift,rmax = 0; 644 Scalar *aa = a->a, *ap; 645 646 PetscFunctionBegin; 647 if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 648 649 if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 650 for ( i=1; i<m; i++ ) { 651 /* move each row back by the amount of empty slots (fshift) before it*/ 652 fshift += imax[i-1] - ailen[i-1]; 653 rmax = PetscMax(rmax,ailen[i]); 654 if (fshift) { 655 ip = aj + ai[i] + shift; ap = aa + ai[i] + shift; 656 N = ailen[i]; 657 for ( j=0; j<N; j++ ) { 658 ip[j-fshift] = ip[j]; 659 ap[j-fshift] = ap[j]; 660 } 661 } 662 ai[i] = ai[i-1] + ailen[i-1]; 663 } 664 if (m) { 665 fshift += imax[m-1] - ailen[m-1]; 666 ai[m] = ai[m-1] + ailen[m-1]; 667 } 668 /* reset ilen and imax for each row */ 669 for ( i=0; i<m; i++ ) { 670 ailen[i] = imax[i] = ai[i+1] - ai[i]; 671 } 672 a->nz = ai[m] + shift; 673 674 /* diagonals may have moved, so kill the diagonal pointers */ 675 if (fshift && a->diag) { 676 PetscFree(a->diag); 677 PLogObjectMemory(A,-(m+1)*sizeof(int)); 678 a->diag = 0; 679 } 680 PLogInfo(A,"MatAssemblyEnd_SeqAIJ:Matrix size: %d X %d; storage space: %d unneeded, %d used\n", 681 m,a->n,fshift,a->nz); 682 PLogInfo(A,"MatAssemblyEnd_SeqAIJ:Number of mallocs during MatSetValues is %d\n", 683 a->reallocs); 684 PLogInfo(A,"MatAssemblyEnd_SeqAIJ:Most nonzeros in any row is %d\n",rmax); 685 a->reallocs = 0; 686 A->info.nz_unneeded = (double)fshift; 687 688 /* check out for identical nodes. If found, use inode functions */ 689 ierr = Mat_AIJ_CheckInode(A); CHKERRQ(ierr); 690 PetscFunctionReturn(0); 691 } 692 693 #undef __FUNC__ 694 #define __FUNC__ "MatZeroEntries_SeqAIJ" 695 int MatZeroEntries_SeqAIJ(Mat A) 696 { 697 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 698 699 PetscFunctionBegin; 700 PetscMemzero(a->a,(a->i[a->m]+a->indexshift)*sizeof(Scalar)); 701 PetscFunctionReturn(0); 702 } 703 704 #undef __FUNC__ 705 #define __FUNC__ "MatDestroy_SeqAIJ" 706 int MatDestroy_SeqAIJ(Mat A) 707 { 708 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 709 int ierr; 710 711 PetscFunctionBegin; 712 #if defined(USE_PETSC_LOG) 713 PLogObjectState((PetscObject)A,"Rows=%d, Cols=%d, NZ=%d",a->m,a->n,a->nz); 714 #endif 715 PetscFree(a->a); 716 if (!a->singlemalloc) { PetscFree(a->i); PetscFree(a->j);} 717 if (a->diag) PetscFree(a->diag); 718 if (a->ilen) PetscFree(a->ilen); 719 if (a->imax) PetscFree(a->imax); 720 if (a->solve_work) PetscFree(a->solve_work); 721 if (a->inode.size) PetscFree(a->inode.size); 722 if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);} 723 PetscFree(a); 724 725 PLogObjectDestroy(A); 726 PetscHeaderDestroy(A); 727 PetscFunctionReturn(0); 728 } 729 730 #undef __FUNC__ 731 #define __FUNC__ "MatCompress_SeqAIJ" 732 int MatCompress_SeqAIJ(Mat A) 733 { 734 PetscFunctionBegin; 735 PetscFunctionReturn(0); 736 } 737 738 #undef __FUNC__ 739 #define __FUNC__ "MatSetOption_SeqAIJ" 740 int MatSetOption_SeqAIJ(Mat A,MatOption op) 741 { 742 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 743 744 PetscFunctionBegin; 745 if (op == MAT_ROW_ORIENTED) a->roworiented = 1; 746 else if (op == MAT_COLUMN_ORIENTED) a->roworiented = 0; 747 else if (op == MAT_COLUMNS_SORTED) a->sorted = 1; 748 else if (op == MAT_COLUMNS_UNSORTED) a->sorted = 0; 749 else if (op == MAT_NO_NEW_NONZERO_LOCATIONS) a->nonew = 1; 750 else if (op == MAT_NEW_NONZERO_LOCATION_ERROR) a->nonew = -1; 751 else if (op == MAT_NEW_NONZERO_ALLOCATION_ERROR) a->nonew = -2; 752 else if (op == MAT_YES_NEW_NONZERO_LOCATIONS) a->nonew = 0; 753 else if (op == MAT_ROWS_SORTED || 754 op == MAT_ROWS_UNSORTED || 755 op == MAT_SYMMETRIC || 756 op == MAT_STRUCTURALLY_SYMMETRIC || 757 op == MAT_YES_NEW_DIAGONALS || 758 op == MAT_IGNORE_OFF_PROC_ENTRIES|| 759 op == MAT_USE_HASH_TABLE) 760 PLogInfo(A,"MatSetOption_SeqAIJ:Option ignored\n"); 761 else if (op == MAT_NO_NEW_DIAGONALS) { 762 SETERRQ(PETSC_ERR_SUP,0,"MAT_NO_NEW_DIAGONALS"); 763 } else if (op == MAT_INODE_LIMIT_1) a->inode.limit = 1; 764 else if (op == MAT_INODE_LIMIT_2) a->inode.limit = 2; 765 else if (op == MAT_INODE_LIMIT_3) a->inode.limit = 3; 766 else if (op == MAT_INODE_LIMIT_4) a->inode.limit = 4; 767 else if (op == MAT_INODE_LIMIT_5) a->inode.limit = 5; 768 else SETERRQ(PETSC_ERR_SUP,0,"unknown option"); 769 PetscFunctionReturn(0); 770 } 771 772 #undef __FUNC__ 773 #define __FUNC__ "MatGetDiagonal_SeqAIJ" 774 int MatGetDiagonal_SeqAIJ(Mat A,Vec v) 775 { 776 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 777 int i,j, n,shift = a->indexshift,ierr; 778 Scalar *x, zero = 0.0; 779 780 PetscFunctionBegin; 781 ierr = VecSet(&zero,v);CHKERRQ(ierr); 782 ierr = VecGetArray(v,&x);;CHKERRQ(ierr); 783 ierr = VecGetLocalSize(v,&n);;CHKERRQ(ierr); 784 if (n != a->m) SETERRQ(PETSC_ERR_ARG_SIZ,0,"Nonconforming matrix and vector"); 785 for ( i=0; i<a->m; i++ ) { 786 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 787 if (a->j[j]+shift == i) { 788 x[i] = a->a[j]; 789 break; 790 } 791 } 792 } 793 ierr = VecRestoreArray(v,&x);;CHKERRQ(ierr); 794 PetscFunctionReturn(0); 795 } 796 797 /* -------------------------------------------------------*/ 798 /* Should check that shapes of vectors and matrices match */ 799 /* -------------------------------------------------------*/ 800 #undef __FUNC__ 801 #define __FUNC__ "MatMultTrans_SeqAIJ" 802 int MatMultTrans_SeqAIJ(Mat A,Vec xx,Vec yy) 803 { 804 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 805 Scalar *x, *y, *v, alpha; 806 int ierr,m = a->m, n, i, *idx, shift = a->indexshift; 807 808 PetscFunctionBegin; 809 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 810 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 811 PetscMemzero(y,a->n*sizeof(Scalar)); 812 y = y + shift; /* shift for Fortran start by 1 indexing */ 813 for ( i=0; i<m; i++ ) { 814 idx = a->j + a->i[i] + shift; 815 v = a->a + a->i[i] + shift; 816 n = a->i[i+1] - a->i[i]; 817 alpha = x[i]; 818 while (n-->0) {y[*idx++] += alpha * *v++;} 819 } 820 PLogFlops(2*a->nz - a->n); 821 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 822 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 823 PetscFunctionReturn(0); 824 } 825 826 #undef __FUNC__ 827 #define __FUNC__ "MatMultTransAdd_SeqAIJ" 828 int MatMultTransAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy) 829 { 830 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 831 Scalar *x, *y, *v, alpha; 832 int ierr,m = a->m, n, i, *idx,shift = a->indexshift; 833 834 PetscFunctionBegin; 835 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 836 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 837 if (zz != yy) VecCopy(zz,yy); 838 y = y + shift; /* shift for Fortran start by 1 indexing */ 839 for ( i=0; i<m; i++ ) { 840 idx = a->j + a->i[i] + shift; 841 v = a->a + a->i[i] + shift; 842 n = a->i[i+1] - a->i[i]; 843 alpha = x[i]; 844 while (n-->0) {y[*idx++] += alpha * *v++;} 845 } 846 PLogFlops(2*a->nz); 847 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 848 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 849 PetscFunctionReturn(0); 850 } 851 852 #undef __FUNC__ 853 #define __FUNC__ "MatMult_SeqAIJ" 854 int MatMult_SeqAIJ(Mat A,Vec xx,Vec yy) 855 { 856 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 857 Scalar *x, *y, *v, sum; 858 int ierr,m = a->m, *idx, shift = a->indexshift,*ii; 859 #if !defined(USE_FORTRAN_KERNELS) 860 int n, i, jrow,j; 861 #endif 862 863 #if defined(HAVE_PRAGMA_DISJOINT) 864 #pragma disjoint(*x,*y,*v) 865 #endif 866 867 PetscFunctionBegin; 868 ierr = VecGetArray(xx,&x); CHKERRQ(ierr); 869 ierr = VecGetArray(yy,&y); CHKERRQ(ierr); 870 x = x + shift; /* shift for Fortran start by 1 indexing */ 871 idx = a->j; 872 v = a->a; 873 ii = a->i; 874 #if defined(USE_FORTRAN_KERNELS) 875 fortranmultaij_(&m,x,ii,idx+shift,v+shift,y); 876 #else 877 v += shift; /* shift for Fortran start by 1 indexing */ 878 idx += shift; 879 for ( i=0; i<m; i++ ) { 880 jrow = ii[i]; 881 n = ii[i+1] - jrow; 882 sum = 0.0; 883 for ( j=0; j<n; j++) { 884 sum += v[jrow]*x[idx[jrow]]; jrow++; 885 } 886 y[i] = sum; 887 } 888 #endif 889 PLogFlops(2*a->nz - m); 890 ierr = VecRestoreArray(xx,&x); CHKERRQ(ierr); 891 ierr = VecRestoreArray(yy,&y); CHKERRQ(ierr); 892 PetscFunctionReturn(0); 893 } 894 895 #undef __FUNC__ 896 #define __FUNC__ "MatMultAdd_SeqAIJ" 897 int MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz) 898 { 899 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 900 Scalar *x, *y, *z, *v, sum; 901 int ierr,m = a->m, *idx, shift = a->indexshift,*ii; 902 #if !defined(USE_FORTRAN_KERNELS) 903 int n,i,jrow,j; 904 #endif 905 906 PetscFunctionBegin; 907 ierr = VecGetArray(xx,&x); CHKERRQ(ierr); 908 ierr = VecGetArray(yy,&y); CHKERRQ(ierr); 909 ierr = VecGetArray(zz,&z); CHKERRQ(ierr); 910 x = x + shift; /* shift for Fortran start by 1 indexing */ 911 idx = a->j; 912 v = a->a; 913 ii = a->i; 914 #if defined(USE_FORTRAN_KERNELS) 915 fortranmultaddaij_(&m,x,ii,idx+shift,v+shift,y,z); 916 #else 917 v += shift; /* shift for Fortran start by 1 indexing */ 918 idx += shift; 919 for ( i=0; i<m; i++ ) { 920 jrow = ii[i]; 921 n = ii[i+1] - jrow; 922 sum = y[i]; 923 for ( j=0; j<n; j++) { 924 sum += v[jrow]*x[idx[jrow]]; jrow++; 925 } 926 z[i] = sum; 927 } 928 #endif 929 PLogFlops(2*a->nz); 930 ierr = VecRestoreArray(xx,&x); CHKERRQ(ierr); 931 ierr = VecRestoreArray(yy,&y); CHKERRQ(ierr); 932 ierr = VecRestoreArray(zz,&z); CHKERRQ(ierr); 933 PetscFunctionReturn(0); 934 } 935 936 /* 937 Adds diagonal pointers to sparse matrix structure. 938 */ 939 940 #undef __FUNC__ 941 #define __FUNC__ "MatMarkDiag_SeqAIJ" 942 int MatMarkDiag_SeqAIJ(Mat A) 943 { 944 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 945 int i,j, *diag, m = a->m,shift = a->indexshift; 946 947 PetscFunctionBegin; 948 diag = (int *) PetscMalloc( (m+1)*sizeof(int)); CHKPTRQ(diag); 949 PLogObjectMemory(A,(m+1)*sizeof(int)); 950 for ( i=0; i<a->m; i++ ) { 951 for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) { 952 if (a->j[j]+shift == i) { 953 diag[i] = j - shift; 954 break; 955 } 956 } 957 } 958 a->diag = diag; 959 PetscFunctionReturn(0); 960 } 961 962 #undef __FUNC__ 963 #define __FUNC__ "MatRelax_SeqAIJ" 964 int MatRelax_SeqAIJ(Mat A,Vec bb,double omega,MatSORType flag, 965 double fshift,int its,Vec xx) 966 { 967 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 968 Scalar *x, *b, *bs, d, *xs, sum, *v = a->a,*t,scale,*ts, *xb; 969 int ierr, *idx, *diag,n = a->n, m = a->m, i, shift = a->indexshift; 970 971 PetscFunctionBegin; 972 ierr = VecGetArray(xx,&x); CHKERRQ(ierr); 973 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 974 if (!a->diag) {ierr = MatMarkDiag_SeqAIJ(A);CHKERRQ(ierr);} 975 diag = a->diag; 976 xs = x + shift; /* shifted by one for index start of a or a->j*/ 977 if (flag == SOR_APPLY_UPPER) { 978 /* apply ( U + D/omega) to the vector */ 979 bs = b + shift; 980 for ( i=0; i<m; i++ ) { 981 d = fshift + a->a[diag[i] + shift]; 982 n = a->i[i+1] - diag[i] - 1; 983 idx = a->j + diag[i] + (!shift); 984 v = a->a + diag[i] + (!shift); 985 sum = b[i]*d/omega; 986 SPARSEDENSEDOT(sum,bs,v,idx,n); 987 x[i] = sum; 988 } 989 PetscFunctionReturn(0); 990 } 991 if (flag == SOR_APPLY_LOWER) { 992 SETERRQ(PETSC_ERR_SUP,0,"SOR_APPLY_LOWER is not done"); 993 } else if (flag & SOR_EISENSTAT) { 994 /* Let A = L + U + D; where L is lower trianglar, 995 U is upper triangular, E is diagonal; This routine applies 996 997 (L + E)^{-1} A (U + E)^{-1} 998 999 to a vector efficiently using Eisenstat's trick. This is for 1000 the case of SSOR preconditioner, so E is D/omega where omega 1001 is the relaxation factor. 1002 */ 1003 t = (Scalar *) PetscMalloc( m*sizeof(Scalar) ); CHKPTRQ(t); 1004 scale = (2.0/omega) - 1.0; 1005 1006 /* x = (E + U)^{-1} b */ 1007 for ( i=m-1; i>=0; i-- ) { 1008 d = fshift + a->a[diag[i] + shift]; 1009 n = a->i[i+1] - diag[i] - 1; 1010 idx = a->j + diag[i] + (!shift); 1011 v = a->a + diag[i] + (!shift); 1012 sum = b[i]; 1013 SPARSEDENSEMDOT(sum,xs,v,idx,n); 1014 x[i] = omega*(sum/d); 1015 } 1016 1017 /* t = b - (2*E - D)x */ 1018 v = a->a; 1019 for ( i=0; i<m; i++ ) { t[i] = b[i] - scale*(v[*diag++ + shift])*x[i]; } 1020 1021 /* t = (E + L)^{-1}t */ 1022 ts = t + shift; /* shifted by one for index start of a or a->j*/ 1023 diag = a->diag; 1024 for ( i=0; i<m; i++ ) { 1025 d = fshift + a->a[diag[i]+shift]; 1026 n = diag[i] - a->i[i]; 1027 idx = a->j + a->i[i] + shift; 1028 v = a->a + a->i[i] + shift; 1029 sum = t[i]; 1030 SPARSEDENSEMDOT(sum,ts,v,idx,n); 1031 t[i] = omega*(sum/d); 1032 } 1033 1034 /* x = x + t */ 1035 for ( i=0; i<m; i++ ) { x[i] += t[i]; } 1036 PetscFree(t); 1037 PetscFunctionReturn(0); 1038 } 1039 if (flag & SOR_ZERO_INITIAL_GUESS) { 1040 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 1041 for ( i=0; i<m; i++ ) { 1042 d = fshift + a->a[diag[i]+shift]; 1043 n = diag[i] - a->i[i]; 1044 idx = a->j + a->i[i] + shift; 1045 v = a->a + a->i[i] + shift; 1046 sum = b[i]; 1047 SPARSEDENSEMDOT(sum,xs,v,idx,n); 1048 x[i] = omega*(sum/d); 1049 } 1050 xb = x; 1051 } else xb = b; 1052 if ((flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) && 1053 (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP)) { 1054 for ( i=0; i<m; i++ ) { 1055 x[i] *= a->a[diag[i]+shift]; 1056 } 1057 } 1058 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 1059 for ( i=m-1; i>=0; i-- ) { 1060 d = fshift + a->a[diag[i] + shift]; 1061 n = a->i[i+1] - diag[i] - 1; 1062 idx = a->j + diag[i] + (!shift); 1063 v = a->a + diag[i] + (!shift); 1064 sum = xb[i]; 1065 SPARSEDENSEMDOT(sum,xs,v,idx,n); 1066 x[i] = omega*(sum/d); 1067 } 1068 } 1069 its--; 1070 } 1071 while (its--) { 1072 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 1073 for ( i=0; i<m; i++ ) { 1074 d = fshift + a->a[diag[i]+shift]; 1075 n = a->i[i+1] - a->i[i]; 1076 idx = a->j + a->i[i] + shift; 1077 v = a->a + a->i[i] + shift; 1078 sum = b[i]; 1079 SPARSEDENSEMDOT(sum,xs,v,idx,n); 1080 x[i] = (1. - omega)*x[i] + omega*(sum + a->a[diag[i]+shift]*x[i])/d; 1081 } 1082 } 1083 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 1084 for ( i=m-1; i>=0; i-- ) { 1085 d = fshift + a->a[diag[i] + shift]; 1086 n = a->i[i+1] - a->i[i]; 1087 idx = a->j + a->i[i] + shift; 1088 v = a->a + a->i[i] + shift; 1089 sum = b[i]; 1090 SPARSEDENSEMDOT(sum,xs,v,idx,n); 1091 x[i] = (1. - omega)*x[i] + omega*(sum + a->a[diag[i]+shift]*x[i])/d; 1092 } 1093 } 1094 } 1095 PetscFunctionReturn(0); 1096 } 1097 1098 #undef __FUNC__ 1099 #define __FUNC__ "MatGetInfo_SeqAIJ" 1100 int MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info) 1101 { 1102 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 1103 1104 PetscFunctionBegin; 1105 info->rows_global = (double)a->m; 1106 info->columns_global = (double)a->n; 1107 info->rows_local = (double)a->m; 1108 info->columns_local = (double)a->n; 1109 info->block_size = 1.0; 1110 info->nz_allocated = (double)a->maxnz; 1111 info->nz_used = (double)a->nz; 1112 info->nz_unneeded = (double)(a->maxnz - a->nz); 1113 /* if (info->nz_unneeded != A->info.nz_unneeded) 1114 printf("space descrepancy: maxnz-nz = %d, nz_unneeded = %d\n",(int)info->nz_unneeded,(int)A->info.nz_unneeded); */ 1115 info->assemblies = (double)A->num_ass; 1116 info->mallocs = (double)a->reallocs; 1117 info->memory = A->mem; 1118 if (A->factor) { 1119 info->fill_ratio_given = A->info.fill_ratio_given; 1120 info->fill_ratio_needed = A->info.fill_ratio_needed; 1121 info->factor_mallocs = A->info.factor_mallocs; 1122 } else { 1123 info->fill_ratio_given = 0; 1124 info->fill_ratio_needed = 0; 1125 info->factor_mallocs = 0; 1126 } 1127 PetscFunctionReturn(0); 1128 } 1129 1130 extern int MatLUFactorSymbolic_SeqAIJ(Mat,IS,IS,double,Mat*); 1131 extern int MatLUFactorNumeric_SeqAIJ(Mat,Mat*); 1132 extern int MatLUFactor_SeqAIJ(Mat,IS,IS,double); 1133 extern int MatSolve_SeqAIJ(Mat,Vec,Vec); 1134 extern int MatSolveAdd_SeqAIJ(Mat,Vec,Vec,Vec); 1135 extern int MatSolveTrans_SeqAIJ(Mat,Vec,Vec); 1136 extern int MatSolveTransAdd_SeqAIJ(Mat,Vec,Vec,Vec); 1137 1138 #undef __FUNC__ 1139 #define __FUNC__ "MatZeroRows_SeqAIJ" 1140 int MatZeroRows_SeqAIJ(Mat A,IS is,Scalar *diag) 1141 { 1142 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 1143 int i,ierr,N, *rows,m = a->m - 1,shift = a->indexshift; 1144 1145 PetscFunctionBegin; 1146 ierr = ISGetSize(is,&N); CHKERRQ(ierr); 1147 ierr = ISGetIndices(is,&rows); CHKERRQ(ierr); 1148 if (diag) { 1149 for ( i=0; i<N; i++ ) { 1150 if (rows[i] < 0 || rows[i] > m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"row out of range"); 1151 if (a->ilen[rows[i]] > 0) { /* in case row was completely empty */ 1152 a->ilen[rows[i]] = 1; 1153 a->a[a->i[rows[i]]+shift] = *diag; 1154 a->j[a->i[rows[i]]+shift] = rows[i]+shift; 1155 } else { 1156 ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],diag,INSERT_VALUES);CHKERRQ(ierr); 1157 } 1158 } 1159 } else { 1160 for ( i=0; i<N; i++ ) { 1161 if (rows[i] < 0 || rows[i] > m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"row out of range"); 1162 a->ilen[rows[i]] = 0; 1163 } 1164 } 1165 ISRestoreIndices(is,&rows); 1166 ierr = MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 1167 PetscFunctionReturn(0); 1168 } 1169 1170 #undef __FUNC__ 1171 #define __FUNC__ "MatGetSize_SeqAIJ" 1172 int MatGetSize_SeqAIJ(Mat A,int *m,int *n) 1173 { 1174 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 1175 1176 PetscFunctionBegin; 1177 if (m) *m = a->m; 1178 if (n) *n = a->n; 1179 PetscFunctionReturn(0); 1180 } 1181 1182 #undef __FUNC__ 1183 #define __FUNC__ "MatGetOwnershipRange_SeqAIJ" 1184 int MatGetOwnershipRange_SeqAIJ(Mat A,int *m,int *n) 1185 { 1186 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 1187 1188 PetscFunctionBegin; 1189 *m = 0; *n = a->m; 1190 PetscFunctionReturn(0); 1191 } 1192 1193 #undef __FUNC__ 1194 #define __FUNC__ "MatGetRow_SeqAIJ" 1195 int MatGetRow_SeqAIJ(Mat A,int row,int *nz,int **idx,Scalar **v) 1196 { 1197 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 1198 int *itmp,i,shift = a->indexshift; 1199 1200 PetscFunctionBegin; 1201 if (row < 0 || row >= a->m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row out of range"); 1202 1203 *nz = a->i[row+1] - a->i[row]; 1204 if (v) *v = a->a + a->i[row] + shift; 1205 if (idx) { 1206 itmp = a->j + a->i[row] + shift; 1207 if (*nz && shift) { 1208 *idx = (int *) PetscMalloc( (*nz)*sizeof(int) ); CHKPTRQ(*idx); 1209 for ( i=0; i<(*nz); i++ ) {(*idx)[i] = itmp[i] + shift;} 1210 } else if (*nz) { 1211 *idx = itmp; 1212 } 1213 else *idx = 0; 1214 } 1215 PetscFunctionReturn(0); 1216 } 1217 1218 #undef __FUNC__ 1219 #define __FUNC__ "MatRestoreRow_SeqAIJ" 1220 int MatRestoreRow_SeqAIJ(Mat A,int row,int *nz,int **idx,Scalar **v) 1221 { 1222 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 1223 1224 PetscFunctionBegin; 1225 if (idx) {if (*idx && a->indexshift) PetscFree(*idx);} 1226 PetscFunctionReturn(0); 1227 } 1228 1229 #undef __FUNC__ 1230 #define __FUNC__ "MatNorm_SeqAIJ" 1231 int MatNorm_SeqAIJ(Mat A,NormType type,double *norm) 1232 { 1233 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 1234 Scalar *v = a->a; 1235 double sum = 0.0; 1236 int i, j,shift = a->indexshift; 1237 1238 PetscFunctionBegin; 1239 if (type == NORM_FROBENIUS) { 1240 for (i=0; i<a->nz; i++ ) { 1241 #if defined(USE_PETSC_COMPLEX) 1242 sum += real(conj(*v)*(*v)); v++; 1243 #else 1244 sum += (*v)*(*v); v++; 1245 #endif 1246 } 1247 *norm = sqrt(sum); 1248 } else if (type == NORM_1) { 1249 double *tmp; 1250 int *jj = a->j; 1251 tmp = (double *) PetscMalloc( (a->n+1)*sizeof(double) ); CHKPTRQ(tmp); 1252 PetscMemzero(tmp,a->n*sizeof(double)); 1253 *norm = 0.0; 1254 for ( j=0; j<a->nz; j++ ) { 1255 tmp[*jj++ + shift] += PetscAbsScalar(*v); v++; 1256 } 1257 for ( j=0; j<a->n; j++ ) { 1258 if (tmp[j] > *norm) *norm = tmp[j]; 1259 } 1260 PetscFree(tmp); 1261 } else if (type == NORM_INFINITY) { 1262 *norm = 0.0; 1263 for ( j=0; j<a->m; j++ ) { 1264 v = a->a + a->i[j] + shift; 1265 sum = 0.0; 1266 for ( i=0; i<a->i[j+1]-a->i[j]; i++ ) { 1267 sum += PetscAbsScalar(*v); v++; 1268 } 1269 if (sum > *norm) *norm = sum; 1270 } 1271 } else { 1272 SETERRQ(PETSC_ERR_SUP,0,"No support for two norm"); 1273 } 1274 PetscFunctionReturn(0); 1275 } 1276 1277 #undef __FUNC__ 1278 #define __FUNC__ "MatTranspose_SeqAIJ" 1279 int MatTranspose_SeqAIJ(Mat A,Mat *B) 1280 { 1281 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 1282 Mat C; 1283 int i, ierr, *aj = a->j, *ai = a->i, m = a->m, len, *col; 1284 int shift = a->indexshift; 1285 Scalar *array = a->a; 1286 1287 PetscFunctionBegin; 1288 if (B == PETSC_NULL && m != a->n) SETERRQ(PETSC_ERR_ARG_SIZ,0,"Square matrix only for in-place"); 1289 col = (int *) PetscMalloc((1+a->n)*sizeof(int)); CHKPTRQ(col); 1290 PetscMemzero(col,(1+a->n)*sizeof(int)); 1291 if (shift) { 1292 for ( i=0; i<ai[m]-1; i++ ) aj[i] -= 1; 1293 } 1294 for ( i=0; i<ai[m]+shift; i++ ) col[aj[i]] += 1; 1295 ierr = MatCreateSeqAIJ(A->comm,a->n,m,0,col,&C); CHKERRQ(ierr); 1296 PetscFree(col); 1297 for ( i=0; i<m; i++ ) { 1298 len = ai[i+1]-ai[i]; 1299 ierr = MatSetValues(C,len,aj,1,&i,array,INSERT_VALUES); CHKERRQ(ierr); 1300 array += len; aj += len; 1301 } 1302 if (shift) { 1303 for ( i=0; i<ai[m]-1; i++ ) aj[i] += 1; 1304 } 1305 1306 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 1307 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 1308 1309 if (B != PETSC_NULL) { 1310 *B = C; 1311 } else { 1312 PetscOps *Abops; 1313 struct _MatOps *Aops; 1314 1315 /* This isn't really an in-place transpose */ 1316 PetscFree(a->a); 1317 if (!a->singlemalloc) {PetscFree(a->i); PetscFree(a->j);} 1318 if (a->diag) PetscFree(a->diag); 1319 if (a->ilen) PetscFree(a->ilen); 1320 if (a->imax) PetscFree(a->imax); 1321 if (a->solve_work) PetscFree(a->solve_work); 1322 if (a->inode.size) PetscFree(a->inode.size); 1323 PetscFree(a); 1324 1325 /* 1326 This is horrible, horrible code. We need to keep the 1327 the bops and ops Structures, copy everything from C 1328 including the function pointers.. 1329 */ 1330 PetscMemcpy(A->ops,C->ops,sizeof(struct _MatOps)); 1331 PetscMemcpy(A->bops,C->bops,sizeof(PetscOps)); 1332 Abops = A->bops; 1333 Aops = A->ops; 1334 PetscMemcpy(A,C,sizeof(struct _p_Mat)); 1335 A->bops = Abops; 1336 A->ops = Aops; 1337 1338 PetscHeaderDestroy(C); 1339 } 1340 PetscFunctionReturn(0); 1341 } 1342 1343 #undef __FUNC__ 1344 #define __FUNC__ "MatDiagonalScale_SeqAIJ" 1345 int MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr) 1346 { 1347 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 1348 Scalar *l,*r,x,*v; 1349 int ierr,i,j,m = a->m, n = a->n, M, nz = a->nz, *jj,shift = a->indexshift; 1350 1351 PetscFunctionBegin; 1352 if (ll) { 1353 /* The local size is used so that VecMPI can be passed to this routine 1354 by MatDiagonalScale_MPIAIJ */ 1355 ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr); 1356 if (m != a->m) SETERRQ(PETSC_ERR_ARG_SIZ,0,"Left scaling vector wrong length"); 1357 ierr = VecGetArray(ll,&l); CHKERRQ(ierr); 1358 v = a->a; 1359 for ( i=0; i<m; i++ ) { 1360 x = l[i]; 1361 M = a->i[i+1] - a->i[i]; 1362 for ( j=0; j<M; j++ ) { (*v++) *= x;} 1363 } 1364 ierr = VecRestoreArray(ll,&l); CHKERRQ(ierr); 1365 PLogFlops(nz); 1366 } 1367 if (rr) { 1368 ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr); 1369 if (n != a->n) SETERRQ(PETSC_ERR_ARG_SIZ,0,"Right scaling vector wrong length"); 1370 ierr = VecGetArray(rr,&r);CHKERRQ(ierr); 1371 v = a->a; jj = a->j; 1372 for ( i=0; i<nz; i++ ) { 1373 (*v++) *= r[*jj++ + shift]; 1374 } 1375 ierr = VecRestoreArray(rr,&r);CHKERRQ(ierr); 1376 PLogFlops(nz); 1377 } 1378 PetscFunctionReturn(0); 1379 } 1380 1381 #undef __FUNC__ 1382 #define __FUNC__ "MatGetSubMatrix_SeqAIJ" 1383 int MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,int csize,MatGetSubMatrixCall scall,Mat *B) 1384 { 1385 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data,*c; 1386 int *smap, i, k, kstart, kend, ierr, oldcols = a->n,*lens; 1387 int row,mat_i,*mat_j,tcol,first,step,*mat_ilen; 1388 register int sum,lensi; 1389 int *irow, *icol, nrows, ncols, shift = a->indexshift,*ssmap; 1390 int *starts,*j_new,*i_new,*aj = a->j, *ai = a->i,ii,*ailen = a->ilen; 1391 Scalar *a_new,*mat_a; 1392 Mat C; 1393 PetscTruth stride; 1394 1395 PetscFunctionBegin; 1396 ierr = ISSorted(isrow,(PetscTruth*)&i);CHKERRQ(ierr); 1397 if (!i) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"ISrow is not sorted"); 1398 ierr = ISSorted(iscol,(PetscTruth*)&i);CHKERRQ(ierr); 1399 if (!i) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"IScol is not sorted"); 1400 1401 ierr = ISGetIndices(isrow,&irow); CHKERRQ(ierr); 1402 ierr = ISGetSize(isrow,&nrows); CHKERRQ(ierr); 1403 ierr = ISGetSize(iscol,&ncols); CHKERRQ(ierr); 1404 1405 ierr = ISStrideGetInfo(iscol,&first,&step); CHKERRQ(ierr); 1406 ierr = ISStride(iscol,&stride); CHKERRQ(ierr); 1407 if (stride && step == 1) { 1408 /* special case of contiguous rows */ 1409 lens = (int *) PetscMalloc((ncols+nrows+1)*sizeof(int)); CHKPTRQ(lens); 1410 starts = lens + ncols; 1411 /* loop over new rows determining lens and starting points */ 1412 for (i=0; i<nrows; i++) { 1413 kstart = ai[irow[i]]+shift; 1414 kend = kstart + ailen[irow[i]]; 1415 for ( k=kstart; k<kend; k++ ) { 1416 if (aj[k]+shift >= first) { 1417 starts[i] = k; 1418 break; 1419 } 1420 } 1421 sum = 0; 1422 while (k < kend) { 1423 if (aj[k++]+shift >= first+ncols) break; 1424 sum++; 1425 } 1426 lens[i] = sum; 1427 } 1428 /* create submatrix */ 1429 if (scall == MAT_REUSE_MATRIX) { 1430 int n_cols,n_rows; 1431 ierr = MatGetSize(*B,&n_rows,&n_cols); CHKERRQ(ierr); 1432 if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,0,"Reused submatrix wrong size"); 1433 ierr = MatZeroEntries(*B); CHKERRQ(ierr); 1434 C = *B; 1435 } else { 1436 ierr = MatCreateSeqAIJ(A->comm,nrows,ncols,0,lens,&C);CHKERRQ(ierr); 1437 } 1438 c = (Mat_SeqAIJ*) C->data; 1439 1440 /* loop over rows inserting into submatrix */ 1441 a_new = c->a; 1442 j_new = c->j; 1443 i_new = c->i; 1444 i_new[0] = -shift; 1445 for (i=0; i<nrows; i++) { 1446 ii = starts[i]; 1447 lensi = lens[i]; 1448 for ( k=0; k<lensi; k++ ) { 1449 *j_new++ = aj[ii+k] - first; 1450 } 1451 PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(Scalar)); 1452 a_new += lensi; 1453 i_new[i+1] = i_new[i] + lensi; 1454 c->ilen[i] = lensi; 1455 } 1456 PetscFree(lens); 1457 } else { 1458 ierr = ISGetIndices(iscol,&icol); CHKERRQ(ierr); 1459 smap = (int *) PetscMalloc((1+oldcols)*sizeof(int)); CHKPTRQ(smap); 1460 ssmap = smap + shift; 1461 lens = (int *) PetscMalloc((1+nrows)*sizeof(int)); CHKPTRQ(lens); 1462 PetscMemzero(smap,oldcols*sizeof(int)); 1463 for ( i=0; i<ncols; i++ ) smap[icol[i]] = i+1; 1464 /* determine lens of each row */ 1465 for (i=0; i<nrows; i++) { 1466 kstart = ai[irow[i]]+shift; 1467 kend = kstart + a->ilen[irow[i]]; 1468 lens[i] = 0; 1469 for ( k=kstart; k<kend; k++ ) { 1470 if (ssmap[aj[k]]) { 1471 lens[i]++; 1472 } 1473 } 1474 } 1475 /* Create and fill new matrix */ 1476 if (scall == MAT_REUSE_MATRIX) { 1477 c = (Mat_SeqAIJ *)((*B)->data); 1478 if (c->m != nrows || c->n != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,0,"Cannot reuse matrix. wrong size"); 1479 if (PetscMemcmp(c->ilen,lens, c->m *sizeof(int))) { 1480 SETERRQ(PETSC_ERR_ARG_SIZ,0,"Cannot reuse matrix. wrong no of nonzeros"); 1481 } 1482 PetscMemzero(c->ilen,c->m*sizeof(int)); 1483 C = *B; 1484 } else { 1485 ierr = MatCreateSeqAIJ(A->comm,nrows,ncols,0,lens,&C);CHKERRQ(ierr); 1486 } 1487 c = (Mat_SeqAIJ *)(C->data); 1488 for (i=0; i<nrows; i++) { 1489 row = irow[i]; 1490 kstart = ai[row]+shift; 1491 kend = kstart + a->ilen[row]; 1492 mat_i = c->i[i]+shift; 1493 mat_j = c->j + mat_i; 1494 mat_a = c->a + mat_i; 1495 mat_ilen = c->ilen + i; 1496 for ( k=kstart; k<kend; k++ ) { 1497 if ((tcol=ssmap[a->j[k]])) { 1498 *mat_j++ = tcol - (!shift); 1499 *mat_a++ = a->a[k]; 1500 (*mat_ilen)++; 1501 1502 } 1503 } 1504 } 1505 /* Free work space */ 1506 ierr = ISRestoreIndices(iscol,&icol); CHKERRQ(ierr); 1507 PetscFree(smap); PetscFree(lens); 1508 } 1509 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 1510 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 1511 1512 ierr = ISRestoreIndices(isrow,&irow); CHKERRQ(ierr); 1513 *B = C; 1514 PetscFunctionReturn(0); 1515 } 1516 1517 /* 1518 note: This can only work for identity for row and col. It would 1519 be good to check this and otherwise generate an error. 1520 */ 1521 #undef __FUNC__ 1522 #define __FUNC__ "MatILUFactor_SeqAIJ" 1523 int MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,double efill,int fill) 1524 { 1525 Mat_SeqAIJ *a = (Mat_SeqAIJ *) inA->data; 1526 int ierr; 1527 Mat outA; 1528 1529 PetscFunctionBegin; 1530 if (fill != 0) SETERRQ(PETSC_ERR_SUP,0,"Only fill=0 supported"); 1531 1532 outA = inA; 1533 inA->factor = FACTOR_LU; 1534 a->row = row; 1535 a->col = col; 1536 1537 /* Create the invert permutation so that it can be used in MatLUFactorNumeric() */ 1538 ierr = ISInvertPermutation(col,&(a->icol)); CHKERRQ(ierr); 1539 PLogObjectParent(inA,a->icol); 1540 1541 if (!a->solve_work) { /* this matrix may have been factored before */ 1542 a->solve_work = (Scalar *) PetscMalloc( (a->m+1)*sizeof(Scalar)); CHKPTRQ(a->solve_work); 1543 } 1544 1545 if (!a->diag) { 1546 ierr = MatMarkDiag_SeqAIJ(inA); CHKERRQ(ierr); 1547 } 1548 ierr = MatLUFactorNumeric_SeqAIJ(inA,&outA); CHKERRQ(ierr); 1549 PetscFunctionReturn(0); 1550 } 1551 1552 #include "pinclude/plapack.h" 1553 #undef __FUNC__ 1554 #define __FUNC__ "MatScale_SeqAIJ" 1555 int MatScale_SeqAIJ(Scalar *alpha,Mat inA) 1556 { 1557 Mat_SeqAIJ *a = (Mat_SeqAIJ *) inA->data; 1558 int one = 1; 1559 1560 PetscFunctionBegin; 1561 BLscal_( &a->nz, alpha, a->a, &one ); 1562 PLogFlops(a->nz); 1563 PetscFunctionReturn(0); 1564 } 1565 1566 #undef __FUNC__ 1567 #define __FUNC__ "MatGetSubMatrices_SeqAIJ" 1568 int MatGetSubMatrices_SeqAIJ(Mat A,int n, IS *irow,IS *icol,MatGetSubMatrixCall scall,Mat **B) 1569 { 1570 int ierr,i; 1571 1572 PetscFunctionBegin; 1573 if (scall == MAT_INITIAL_MATRIX) { 1574 *B = (Mat *) PetscMalloc( (n+1)*sizeof(Mat) ); CHKPTRQ(*B); 1575 } 1576 1577 for ( i=0; i<n; i++ ) { 1578 ierr = MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr); 1579 } 1580 PetscFunctionReturn(0); 1581 } 1582 1583 #undef __FUNC__ 1584 #define __FUNC__ "MatGetBlockSize_SeqAIJ" 1585 int MatGetBlockSize_SeqAIJ(Mat A, int *bs) 1586 { 1587 PetscFunctionBegin; 1588 *bs = 1; 1589 PetscFunctionReturn(0); 1590 } 1591 1592 #undef __FUNC__ 1593 #define __FUNC__ "MatIncreaseOverlap_SeqAIJ" 1594 int MatIncreaseOverlap_SeqAIJ(Mat A, int is_max, IS *is, int ov) 1595 { 1596 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 1597 int shift, row, i,j,k,l,m,n, *idx,ierr, *nidx, isz, val; 1598 int start, end, *ai, *aj; 1599 BT table; 1600 1601 PetscFunctionBegin; 1602 shift = a->indexshift; 1603 m = a->m; 1604 ai = a->i; 1605 aj = a->j+shift; 1606 1607 if (ov < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"illegal overlap value used"); 1608 1609 nidx = (int *) PetscMalloc((m+1)*sizeof(int)); CHKPTRQ(nidx); 1610 ierr = BTCreate(m,table); CHKERRQ(ierr); 1611 1612 for ( i=0; i<is_max; i++ ) { 1613 /* Initialize the two local arrays */ 1614 isz = 0; 1615 BTMemzero(m,table); 1616 1617 /* Extract the indices, assume there can be duplicate entries */ 1618 ierr = ISGetIndices(is[i],&idx); CHKERRQ(ierr); 1619 ierr = ISGetSize(is[i],&n); CHKERRQ(ierr); 1620 1621 /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 1622 for ( j=0; j<n ; ++j){ 1623 if(!BTLookupSet(table, idx[j])) { nidx[isz++] = idx[j];} 1624 } 1625 ierr = ISRestoreIndices(is[i],&idx); CHKERRQ(ierr); 1626 ierr = ISDestroy(is[i]); CHKERRQ(ierr); 1627 1628 k = 0; 1629 for ( j=0; j<ov; j++){ /* for each overlap */ 1630 n = isz; 1631 for ( ; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */ 1632 row = nidx[k]; 1633 start = ai[row]; 1634 end = ai[row+1]; 1635 for ( l = start; l<end ; l++){ 1636 val = aj[l] + shift; 1637 if (!BTLookupSet(table,val)) {nidx[isz++] = val;} 1638 } 1639 } 1640 } 1641 ierr = ISCreateGeneral(PETSC_COMM_SELF, isz, nidx, (is+i)); CHKERRQ(ierr); 1642 } 1643 BTDestroy(table); 1644 PetscFree(nidx); 1645 PetscFunctionReturn(0); 1646 } 1647 1648 /* -------------------------------------------------------------- */ 1649 #undef __FUNC__ 1650 #define __FUNC__ "MatPermute_SeqAIJ" 1651 int MatPermute_SeqAIJ(Mat A, IS rowp, IS colp, Mat *B) 1652 { 1653 Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 1654 Scalar *vwork; 1655 int i, ierr, nz, m = a->m, n = a->n, *cwork; 1656 int *row,*col,*cnew,j,*lens; 1657 IS icolp,irowp; 1658 1659 PetscFunctionBegin; 1660 ierr = ISInvertPermutation(rowp,&irowp); CHKERRQ(ierr); 1661 ierr = ISGetIndices(irowp,&row); CHKERRQ(ierr); 1662 ierr = ISInvertPermutation(colp,&icolp); CHKERRQ(ierr); 1663 ierr = ISGetIndices(icolp,&col); CHKERRQ(ierr); 1664 1665 /* determine lengths of permuted rows */ 1666 lens = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(lens); 1667 for (i=0; i<m; i++ ) { 1668 lens[row[i]] = a->i[i+1] - a->i[i]; 1669 } 1670 ierr = MatCreateSeqAIJ(A->comm,m,n,0,lens,B);CHKERRQ(ierr); 1671 PetscFree(lens); 1672 1673 cnew = (int *) PetscMalloc( n*sizeof(int) ); CHKPTRQ(cnew); 1674 for (i=0; i<m; i++) { 1675 ierr = MatGetRow(A,i,&nz,&cwork,&vwork); CHKERRQ(ierr); 1676 for (j=0; j<nz; j++ ) { cnew[j] = col[cwork[j]];} 1677 ierr = MatSetValues(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES); CHKERRQ(ierr); 1678 ierr = MatRestoreRow(A,i,&nz,&cwork,&vwork); CHKERRQ(ierr); 1679 } 1680 PetscFree(cnew); 1681 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 1682 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 1683 ierr = ISRestoreIndices(irowp,&row); CHKERRQ(ierr); 1684 ierr = ISRestoreIndices(icolp,&col); CHKERRQ(ierr); 1685 ierr = ISDestroy(irowp); CHKERRQ(ierr); 1686 ierr = ISDestroy(icolp); CHKERRQ(ierr); 1687 PetscFunctionReturn(0); 1688 } 1689 1690 #undef __FUNC__ 1691 #define __FUNC__ "MatPrintHelp_SeqAIJ" 1692 int MatPrintHelp_SeqAIJ(Mat A) 1693 { 1694 static int called = 0; 1695 MPI_Comm comm = A->comm; 1696 1697 PetscFunctionBegin; 1698 if (called) {PetscFunctionReturn(0);} else called = 1; 1699 (*PetscHelpPrintf)(comm," Options for MATSEQAIJ and MATMPIAIJ matrix formats (the defaults):\n"); 1700 (*PetscHelpPrintf)(comm," -mat_lu_pivotthreshold <threshold>: Set pivoting threshold\n"); 1701 (*PetscHelpPrintf)(comm," -mat_aij_oneindex: internal indices begin at 1 instead of the default 0.\n"); 1702 (*PetscHelpPrintf)(comm," -mat_aij_no_inode: Do not use inodes\n"); 1703 (*PetscHelpPrintf)(comm," -mat_aij_inode_limit <limit>: Set inode limit (max limit=5)\n"); 1704 #if defined(HAVE_ESSL) 1705 (*PetscHelpPrintf)(comm," -mat_aij_essl: Use IBM sparse LU factorization and solve.\n"); 1706 #endif 1707 PetscFunctionReturn(0); 1708 } 1709 extern int MatEqual_SeqAIJ(Mat A,Mat B, PetscTruth* flg); 1710 extern int MatFDColoringCreate_SeqAIJ(Mat,ISColoring,MatFDColoring); 1711 extern int MatColoringPatch_SeqAIJ(Mat,int,int *,ISColoring *); 1712 1713 /* -------------------------------------------------------------------*/ 1714 static struct _MatOps MatOps = {MatSetValues_SeqAIJ, 1715 MatGetRow_SeqAIJ,MatRestoreRow_SeqAIJ, 1716 MatMult_SeqAIJ,MatMultAdd_SeqAIJ, 1717 MatMultTrans_SeqAIJ,MatMultTransAdd_SeqAIJ, 1718 MatSolve_SeqAIJ,MatSolveAdd_SeqAIJ, 1719 MatSolveTrans_SeqAIJ,MatSolveTransAdd_SeqAIJ, 1720 MatLUFactor_SeqAIJ,0, 1721 MatRelax_SeqAIJ, 1722 MatTranspose_SeqAIJ, 1723 MatGetInfo_SeqAIJ,MatEqual_SeqAIJ, 1724 MatGetDiagonal_SeqAIJ,MatDiagonalScale_SeqAIJ,MatNorm_SeqAIJ, 1725 0,MatAssemblyEnd_SeqAIJ, 1726 MatCompress_SeqAIJ, 1727 MatSetOption_SeqAIJ,MatZeroEntries_SeqAIJ,MatZeroRows_SeqAIJ, 1728 MatLUFactorSymbolic_SeqAIJ,MatLUFactorNumeric_SeqAIJ,0,0, 1729 MatGetSize_SeqAIJ,MatGetSize_SeqAIJ,MatGetOwnershipRange_SeqAIJ, 1730 MatILUFactorSymbolic_SeqAIJ,0, 1731 0,0, 1732 MatConvertSameType_SeqAIJ,0,0, 1733 MatILUFactor_SeqAIJ,0,0, 1734 MatGetSubMatrices_SeqAIJ,MatIncreaseOverlap_SeqAIJ, 1735 MatGetValues_SeqAIJ,0, 1736 MatPrintHelp_SeqAIJ, 1737 MatScale_SeqAIJ,0,0, 1738 MatILUDTFactor_SeqAIJ, 1739 MatGetBlockSize_SeqAIJ, 1740 MatGetRowIJ_SeqAIJ, 1741 MatRestoreRowIJ_SeqAIJ, 1742 MatGetColumnIJ_SeqAIJ, 1743 MatRestoreColumnIJ_SeqAIJ, 1744 MatFDColoringCreate_SeqAIJ, 1745 MatColoringPatch_SeqAIJ, 1746 0, 1747 MatPermute_SeqAIJ}; 1748 1749 extern int MatUseSuperLU_SeqAIJ(Mat); 1750 extern int MatUseEssl_SeqAIJ(Mat); 1751 extern int MatUseDXML_SeqAIJ(Mat); 1752 1753 #undef __FUNC__ 1754 #define __FUNC__ "MatCreateSeqAIJ" 1755 /*@C 1756 MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format 1757 (the default parallel PETSc format). For good matrix assembly performance 1758 the user should preallocate the matrix storage by setting the parameter nz 1759 (or the array nzz). By setting these parameters accurately, performance 1760 during matrix assembly can be increased by more than a factor of 50. 1761 1762 Input Parameters: 1763 . comm - MPI communicator, set to PETSC_COMM_SELF 1764 . m - number of rows 1765 . n - number of columns 1766 . nz - number of nonzeros per row (same for all rows) 1767 . nzz - array containing the number of nonzeros in the various rows 1768 (possibly different for each row) or PETSC_NULL 1769 1770 Output Parameter: 1771 . A - the matrix 1772 1773 Collective on MPI_Comm 1774 1775 Notes: 1776 The AIJ format (also called the Yale sparse matrix format or 1777 compressed row storage), is fully compatible with standard Fortran 77 1778 storage. That is, the stored row and column indices can begin at 1779 either one (as in Fortran) or zero. See the users' manual for details. 1780 1781 Specify the preallocated storage with either nz or nnz (not both). 1782 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 1783 allocation. For large problems you MUST preallocate memory or you 1784 will get TERRIBLE performance, see the users' manual chapter on matrices. 1785 1786 By default, this format uses inodes (identical nodes) when possible, to 1787 improve numerical efficiency of matrix-vector products and solves. We 1788 search for consecutive rows with the same nonzero structure, thereby 1789 reusing matrix information to achieve increased efficiency. 1790 1791 Options Database Keys: 1792 $ -mat_aij_no_inode - Do not use inodes 1793 $ -mat_aij_inode_limit <limit> - Set inode limit. 1794 $ (max limit=5) 1795 $ -mat_aij_oneindex - Internally use indexing starting at 1 1796 $ rather than 0. Note: When calling MatSetValues(), 1797 $ the user still MUST index entries starting at 0! 1798 1799 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues() 1800 @*/ 1801 int MatCreateSeqAIJ(MPI_Comm comm,int m,int n,int nz,int *nnz, Mat *A) 1802 { 1803 Mat B; 1804 Mat_SeqAIJ *b; 1805 int i, len, ierr, flg,size; 1806 1807 PetscFunctionBegin; 1808 MPI_Comm_size(comm,&size); 1809 if (size > 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Comm must be of size 1"); 1810 1811 *A = 0; 1812 PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATSEQAIJ,comm,MatDestroy,MatView); 1813 PLogObjectCreate(B); 1814 B->data = (void *) (b = PetscNew(Mat_SeqAIJ)); CHKPTRQ(b); 1815 PetscMemzero(b,sizeof(Mat_SeqAIJ)); 1816 PetscMemcpy(B->ops,&MatOps,sizeof(struct _MatOps)); 1817 B->ops->destroy = MatDestroy_SeqAIJ; 1818 B->ops->view = MatView_SeqAIJ; 1819 B->factor = 0; 1820 B->lupivotthreshold = 1.0; 1821 B->mapping = 0; 1822 ierr = OptionsGetDouble(PETSC_NULL,"-mat_lu_pivotthreshold",&B->lupivotthreshold,&flg); CHKERRQ(ierr); 1823 b->ilu_preserve_row_sums = PETSC_FALSE; 1824 ierr = OptionsHasName(PETSC_NULL,"-pc_ilu_preserve_row_sums",(int*) &b->ilu_preserve_row_sums);CHKERRQ(ierr); 1825 b->row = 0; 1826 b->col = 0; 1827 b->icol = 0; 1828 b->indexshift = 0; 1829 b->reallocs = 0; 1830 ierr = OptionsHasName(PETSC_NULL,"-mat_aij_oneindex", &flg); CHKERRQ(ierr); 1831 if (flg) b->indexshift = -1; 1832 1833 b->m = m; B->m = m; B->M = m; 1834 b->n = n; B->n = n; B->N = n; 1835 b->imax = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(b->imax); 1836 if (nnz == PETSC_NULL) { 1837 if (nz == PETSC_DEFAULT) nz = 10; 1838 else if (nz <= 0) nz = 1; 1839 for ( i=0; i<m; i++ ) b->imax[i] = nz; 1840 nz = nz*m; 1841 } else { 1842 nz = 0; 1843 for ( i=0; i<m; i++ ) {b->imax[i] = nnz[i]; nz += nnz[i];} 1844 } 1845 1846 /* allocate the matrix space */ 1847 len = nz*(sizeof(int) + sizeof(Scalar)) + (b->m+1)*sizeof(int); 1848 b->a = (Scalar *) PetscMalloc( len ); CHKPTRQ(b->a); 1849 b->j = (int *) (b->a + nz); 1850 PetscMemzero(b->j,nz*sizeof(int)); 1851 b->i = b->j + nz; 1852 b->singlemalloc = 1; 1853 1854 b->i[0] = -b->indexshift; 1855 for (i=1; i<m+1; i++) { 1856 b->i[i] = b->i[i-1] + b->imax[i-1]; 1857 } 1858 1859 /* b->ilen will count nonzeros in each row so far. */ 1860 b->ilen = (int *) PetscMalloc((m+1)*sizeof(int)); 1861 PLogObjectMemory(B,len+2*(m+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqAIJ)); 1862 for ( i=0; i<b->m; i++ ) { b->ilen[i] = 0;} 1863 1864 b->nz = 0; 1865 b->maxnz = nz; 1866 b->sorted = 0; 1867 b->roworiented = 1; 1868 b->nonew = 0; 1869 b->diag = 0; 1870 b->solve_work = 0; 1871 b->spptr = 0; 1872 b->inode.node_count = 0; 1873 b->inode.size = 0; 1874 b->inode.limit = 5; 1875 b->inode.max_limit = 5; 1876 B->info.nz_unneeded = (double)b->maxnz; 1877 1878 *A = B; 1879 1880 /* SuperLU is not currently supported through PETSc */ 1881 #if defined(HAVE_SUPERLU) 1882 ierr = OptionsHasName(PETSC_NULL,"-mat_aij_superlu", &flg); CHKERRQ(ierr); 1883 if (flg) { ierr = MatUseSuperLU_SeqAIJ(B); CHKERRQ(ierr); } 1884 #endif 1885 ierr = OptionsHasName(PETSC_NULL,"-mat_aij_essl", &flg); CHKERRQ(ierr); 1886 if (flg) { ierr = MatUseEssl_SeqAIJ(B); CHKERRQ(ierr); } 1887 ierr = OptionsHasName(PETSC_NULL,"-mat_aij_dxml", &flg); CHKERRQ(ierr); 1888 if (flg) { 1889 if (!b->indexshift) SETERRQ( PETSC_ERR_LIB,0,"need -mat_aij_oneindex with -mat_aij_dxml"); 1890 ierr = MatUseDXML_SeqAIJ(B); CHKERRQ(ierr); 1891 } 1892 ierr = OptionsHasName(PETSC_NULL,"-help", &flg); CHKERRQ(ierr); 1893 if (flg) {ierr = MatPrintHelp(B); CHKERRQ(ierr); } 1894 PetscFunctionReturn(0); 1895 } 1896 1897 #undef __FUNC__ 1898 #define __FUNC__ "MatConvertSameType_SeqAIJ" 1899 int MatConvertSameType_SeqAIJ(Mat A,Mat *B,int cpvalues) 1900 { 1901 Mat C; 1902 Mat_SeqAIJ *c,*a = (Mat_SeqAIJ *) A->data; 1903 int i,len, m = a->m,shift = a->indexshift; 1904 1905 PetscFunctionBegin; 1906 *B = 0; 1907 PetscHeaderCreate(C,_p_Mat,struct _MatOps,MAT_COOKIE,MATSEQAIJ,A->comm,MatDestroy,MatView); 1908 PLogObjectCreate(C); 1909 C->data = (void *) (c = PetscNew(Mat_SeqAIJ)); CHKPTRQ(c); 1910 PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps)); 1911 C->ops->destroy = MatDestroy_SeqAIJ; 1912 C->ops->view = MatView_SeqAIJ; 1913 C->factor = A->factor; 1914 c->row = 0; 1915 c->col = 0; 1916 c->icol = 0; 1917 c->indexshift = shift; 1918 C->assembled = PETSC_TRUE; 1919 1920 c->m = C->m = a->m; 1921 c->n = C->n = a->n; 1922 C->M = a->m; 1923 C->N = a->n; 1924 1925 c->imax = (int *) PetscMalloc((m+1)*sizeof(int)); CHKPTRQ(c->imax); 1926 c->ilen = (int *) PetscMalloc((m+1)*sizeof(int)); CHKPTRQ(c->ilen); 1927 for ( i=0; i<m; i++ ) { 1928 c->imax[i] = a->imax[i]; 1929 c->ilen[i] = a->ilen[i]; 1930 } 1931 1932 /* allocate the matrix space */ 1933 c->singlemalloc = 1; 1934 len = (m+1)*sizeof(int)+(a->i[m])*(sizeof(Scalar)+sizeof(int)); 1935 c->a = (Scalar *) PetscMalloc( len ); CHKPTRQ(c->a); 1936 c->j = (int *) (c->a + a->i[m] + shift); 1937 c->i = c->j + a->i[m] + shift; 1938 PetscMemcpy(c->i,a->i,(m+1)*sizeof(int)); 1939 if (m > 0) { 1940 PetscMemcpy(c->j,a->j,(a->i[m]+shift)*sizeof(int)); 1941 if (cpvalues == COPY_VALUES) { 1942 PetscMemcpy(c->a,a->a,(a->i[m]+shift)*sizeof(Scalar)); 1943 } 1944 } 1945 1946 PLogObjectMemory(C,len+2*(m+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqAIJ)); 1947 c->sorted = a->sorted; 1948 c->roworiented = a->roworiented; 1949 c->nonew = a->nonew; 1950 c->ilu_preserve_row_sums = a->ilu_preserve_row_sums; 1951 1952 if (a->diag) { 1953 c->diag = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(c->diag); 1954 PLogObjectMemory(C,(m+1)*sizeof(int)); 1955 for ( i=0; i<m; i++ ) { 1956 c->diag[i] = a->diag[i]; 1957 } 1958 } else c->diag = 0; 1959 c->inode.limit = a->inode.limit; 1960 c->inode.max_limit = a->inode.max_limit; 1961 if (a->inode.size){ 1962 c->inode.size = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(c->inode.size); 1963 c->inode.node_count = a->inode.node_count; 1964 PetscMemcpy( c->inode.size, a->inode.size, (m+1)*sizeof(int)); 1965 } else { 1966 c->inode.size = 0; 1967 c->inode.node_count = 0; 1968 } 1969 c->nz = a->nz; 1970 c->maxnz = a->maxnz; 1971 c->solve_work = 0; 1972 c->spptr = 0; /* Dangerous -I'm throwing away a->spptr */ 1973 1974 *B = C; 1975 PetscFunctionReturn(0); 1976 } 1977 1978 #undef __FUNC__ 1979 #define __FUNC__ "MatLoad_SeqAIJ" 1980 int MatLoad_SeqAIJ(Viewer viewer,MatType type,Mat *A) 1981 { 1982 Mat_SeqAIJ *a; 1983 Mat B; 1984 int i, nz, ierr, fd, header[4],size,*rowlengths = 0,M,N,shift; 1985 MPI_Comm comm; 1986 1987 PetscFunctionBegin; 1988 PetscObjectGetComm((PetscObject) viewer,&comm); 1989 MPI_Comm_size(comm,&size); 1990 if (size > 1) SETERRQ(PETSC_ERR_ARG_SIZ,0,"view must have one processor"); 1991 ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr); 1992 ierr = PetscBinaryRead(fd,header,4,PETSC_INT); CHKERRQ(ierr); 1993 if (header[0] != MAT_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,0,"not matrix object in file"); 1994 M = header[1]; N = header[2]; nz = header[3]; 1995 1996 if (nz < 0) { 1997 SETERRQ(PETSC_ERR_FILE_UNEXPECTED,1,"Matrix stored in special format on disk, cannot load as SeqAIJ"); 1998 } 1999 2000 /* read in row lengths */ 2001 rowlengths = (int*) PetscMalloc( M*sizeof(int) ); CHKPTRQ(rowlengths); 2002 ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT); CHKERRQ(ierr); 2003 2004 /* create our matrix */ 2005 ierr = MatCreateSeqAIJ(comm,M,N,0,rowlengths,A); CHKERRQ(ierr); 2006 B = *A; 2007 a = (Mat_SeqAIJ *) B->data; 2008 shift = a->indexshift; 2009 2010 /* read in column indices and adjust for Fortran indexing*/ 2011 ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT); CHKERRQ(ierr); 2012 if (shift) { 2013 for ( i=0; i<nz; i++ ) { 2014 a->j[i] += 1; 2015 } 2016 } 2017 2018 /* read in nonzero values */ 2019 ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR); CHKERRQ(ierr); 2020 2021 /* set matrix "i" values */ 2022 a->i[0] = -shift; 2023 for ( i=1; i<= M; i++ ) { 2024 a->i[i] = a->i[i-1] + rowlengths[i-1]; 2025 a->ilen[i-1] = rowlengths[i-1]; 2026 } 2027 PetscFree(rowlengths); 2028 2029 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 2030 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 2031 PetscFunctionReturn(0); 2032 } 2033 2034 #undef __FUNC__ 2035 #define __FUNC__ "MatEqual_SeqAIJ" 2036 int MatEqual_SeqAIJ(Mat A,Mat B, PetscTruth* flg) 2037 { 2038 Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data, *b = (Mat_SeqAIJ *)B->data; 2039 2040 PetscFunctionBegin; 2041 if (B->type !=MATSEQAIJ)SETERRQ(PETSC_ERR_ARG_INCOMP,0,"Matrices must be same type"); 2042 2043 /* If the matrix dimensions are not equal, or no of nonzeros or shift */ 2044 if ((a->m != b->m ) || (a->n !=b->n) ||( a->nz != b->nz)|| 2045 (a->indexshift != b->indexshift)) { 2046 *flg = PETSC_FALSE; PetscFunctionReturn(0); 2047 } 2048 2049 /* if the a->i are the same */ 2050 if (PetscMemcmp(a->i,b->i,(a->m+1)*sizeof(int))) { 2051 *flg = PETSC_FALSE; PetscFunctionReturn(0); 2052 } 2053 2054 /* if a->j are the same */ 2055 if (PetscMemcmp(a->j, b->j, (a->nz)*sizeof(int))) { 2056 *flg = PETSC_FALSE; PetscFunctionReturn(0); 2057 } 2058 2059 /* if a->a are the same */ 2060 if (PetscMemcmp(a->a, b->a, (a->nz)*sizeof(Scalar))) { 2061 *flg = PETSC_FALSE; PetscFunctionReturn(0); 2062 } 2063 *flg = PETSC_TRUE; 2064 PetscFunctionReturn(0); 2065 2066 } 2067