1 /*$Id: aij.c,v 1.385 2001/09/07 20:09:22 bsmith Exp $*/ 2 /* 3 Defines the basic matrix operations for the AIJ (compressed row) 4 matrix storage format. 5 */ 6 7 #include "src/mat/impls/aij/seq/aij.h" /*I "petscmat.h" I*/ 8 #include "src/vec/vecimpl.h" 9 #include "src/inline/spops.h" 10 #include "src/inline/dot.h" 11 #include "petscbt.h" 12 13 14 EXTERN int MatToSymmetricIJ_SeqAIJ(int,int*,int*,int,int,int**,int**); 15 16 #undef __FUNCT__ 17 #define __FUNCT__ "MatGetRowIJ_SeqAIJ" 18 int MatGetRowIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *m,int **ia,int **ja,PetscTruth *done) 19 { 20 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 21 int ierr,i,ishift; 22 23 PetscFunctionBegin; 24 *m = A->m; 25 if (!ia) PetscFunctionReturn(0); 26 ishift = a->indexshift; 27 if (symmetric && !A->structurally_symmetric) { 28 ierr = MatToSymmetricIJ_SeqAIJ(A->m,a->i,a->j,ishift,oshift,ia,ja);CHKERRQ(ierr); 29 } else if (oshift == 0 && ishift == -1) { 30 int nz = a->i[A->m] - 1; 31 /* malloc space and subtract 1 from i and j indices */ 32 ierr = PetscMalloc((A->m+1)*sizeof(int),ia);CHKERRQ(ierr); 33 ierr = PetscMalloc((nz+1)*sizeof(int),ja);CHKERRQ(ierr); 34 for (i=0; i<nz; i++) (*ja)[i] = a->j[i] - 1; 35 for (i=0; i<A->m+1; i++) (*ia)[i] = a->i[i] - 1; 36 } else if (oshift == 1 && ishift == 0) { 37 int nz = a->i[A->m]; 38 /* malloc space and add 1 to i and j indices */ 39 ierr = PetscMalloc((A->m+1)*sizeof(int),ia);CHKERRQ(ierr); 40 ierr = PetscMalloc((nz+1)*sizeof(int),ja);CHKERRQ(ierr); 41 for (i=0; i<nz; i++) (*ja)[i] = a->j[i] + 1; 42 for (i=0; i<A->m+1; i++) (*ia)[i] = a->i[i] + 1; 43 } else { 44 *ia = a->i; *ja = a->j; 45 } 46 PetscFunctionReturn(0); 47 } 48 49 #undef __FUNCT__ 50 #define __FUNCT__ "MatRestoreRowIJ_SeqAIJ" 51 int MatRestoreRowIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *n,int **ia,int **ja,PetscTruth *done) 52 { 53 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 54 int ishift = a->indexshift,ierr; 55 56 PetscFunctionBegin; 57 if (!ia) PetscFunctionReturn(0); 58 if ((symmetric && !A->structurally_symmetric) || (oshift == 0 && ishift == -1) || (oshift == 1 && ishift == 0)) { 59 ierr = PetscFree(*ia);CHKERRQ(ierr); 60 ierr = PetscFree(*ja);CHKERRQ(ierr); 61 } 62 PetscFunctionReturn(0); 63 } 64 65 #undef __FUNCT__ 66 #define __FUNCT__ "MatGetColumnIJ_SeqAIJ" 67 int MatGetColumnIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *nn,int **ia,int **ja,PetscTruth *done) 68 { 69 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 70 int ierr,i,ishift = a->indexshift,*collengths,*cia,*cja,n = A->n,m = A->m; 71 int nz = a->i[m]+ishift,row,*jj,mr,col; 72 73 PetscFunctionBegin; 74 *nn = A->n; 75 if (!ia) PetscFunctionReturn(0); 76 if (symmetric) { 77 ierr = MatToSymmetricIJ_SeqAIJ(A->m,a->i,a->j,ishift,oshift,ia,ja);CHKERRQ(ierr); 78 } else { 79 ierr = PetscMalloc((n+1)*sizeof(int),&collengths);CHKERRQ(ierr); 80 ierr = PetscMemzero(collengths,n*sizeof(int));CHKERRQ(ierr); 81 ierr = PetscMalloc((n+1)*sizeof(int),&cia);CHKERRQ(ierr); 82 ierr = PetscMalloc((nz+1)*sizeof(int),&cja);CHKERRQ(ierr); 83 jj = a->j; 84 for (i=0; i<nz; i++) { 85 collengths[jj[i] + ishift]++; 86 } 87 cia[0] = oshift; 88 for (i=0; i<n; i++) { 89 cia[i+1] = cia[i] + collengths[i]; 90 } 91 ierr = PetscMemzero(collengths,n*sizeof(int));CHKERRQ(ierr); 92 jj = a->j; 93 for (row=0; row<m; row++) { 94 mr = a->i[row+1] - a->i[row]; 95 for (i=0; i<mr; i++) { 96 col = *jj++ + ishift; 97 cja[cia[col] + collengths[col]++ - oshift] = row + oshift; 98 } 99 } 100 ierr = PetscFree(collengths);CHKERRQ(ierr); 101 *ia = cia; *ja = cja; 102 } 103 PetscFunctionReturn(0); 104 } 105 106 #undef __FUNCT__ 107 #define __FUNCT__ "MatRestoreColumnIJ_SeqAIJ" 108 int MatRestoreColumnIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *n,int **ia,int **ja,PetscTruth *done) 109 { 110 int ierr; 111 112 PetscFunctionBegin; 113 if (!ia) PetscFunctionReturn(0); 114 115 ierr = PetscFree(*ia);CHKERRQ(ierr); 116 ierr = PetscFree(*ja);CHKERRQ(ierr); 117 118 PetscFunctionReturn(0); 119 } 120 121 #define CHUNKSIZE 15 122 123 #undef __FUNCT__ 124 #define __FUNCT__ "MatSetValues_SeqAIJ" 125 int MatSetValues_SeqAIJ(Mat A,int m,int *im,int n,int *in,PetscScalar *v,InsertMode is) 126 { 127 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 128 int *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,sorted = a->sorted; 129 int *imax = a->imax,*ai = a->i,*ailen = a->ilen; 130 int *aj = a->j,nonew = a->nonew,shift = a->indexshift,ierr; 131 PetscScalar *ap,value,*aa = a->a; 132 PetscTruth ignorezeroentries = ((a->ignorezeroentries && is == ADD_VALUES) ? PETSC_TRUE:PETSC_FALSE); 133 PetscTruth roworiented = a->roworiented; 134 135 PetscFunctionBegin; 136 for (k=0; k<m; k++) { /* loop over added rows */ 137 row = im[k]; 138 if (row < 0) continue; 139 #if defined(PETSC_USE_BOPT_g) 140 if (row >= A->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %d max %d",row,A->m); 141 #endif 142 rp = aj + ai[row] + shift; ap = aa + ai[row] + shift; 143 rmax = imax[row]; nrow = ailen[row]; 144 low = 0; 145 for (l=0; l<n; l++) { /* loop over added columns */ 146 if (in[l] < 0) continue; 147 #if defined(PETSC_USE_BOPT_g) 148 if (in[l] >= A->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %d max %d",in[l],A->n); 149 #endif 150 col = in[l] - shift; 151 if (roworiented) { 152 value = v[l + k*n]; 153 } else { 154 value = v[k + l*m]; 155 } 156 if (value == 0.0 && ignorezeroentries) continue; 157 158 if (!sorted) low = 0; high = nrow; 159 while (high-low > 5) { 160 t = (low+high)/2; 161 if (rp[t] > col) high = t; 162 else low = t; 163 } 164 for (i=low; i<high; i++) { 165 if (rp[i] > col) break; 166 if (rp[i] == col) { 167 if (is == ADD_VALUES) ap[i] += value; 168 else ap[i] = value; 169 goto noinsert; 170 } 171 } 172 if (nonew == 1) goto noinsert; 173 else if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%d,%d) in the matrix",row,col); 174 if (nrow >= rmax) { 175 /* there is no extra room in row, therefore enlarge */ 176 int new_nz = ai[A->m] + CHUNKSIZE,len,*new_i,*new_j; 177 PetscScalar *new_a; 178 179 if (nonew == -2) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%d,%d) in the matrix requiring new malloc()",row,col); 180 181 /* malloc new storage space */ 182 len = new_nz*(sizeof(int)+sizeof(PetscScalar))+(A->m+1)*sizeof(int); 183 ierr = PetscMalloc(len,&new_a);CHKERRQ(ierr); 184 new_j = (int*)(new_a + new_nz); 185 new_i = new_j + new_nz; 186 187 /* copy over old data into new slots */ 188 for (ii=0; ii<row+1; ii++) {new_i[ii] = ai[ii];} 189 for (ii=row+1; ii<A->m+1; ii++) {new_i[ii] = ai[ii]+CHUNKSIZE;} 190 ierr = PetscMemcpy(new_j,aj,(ai[row]+nrow+shift)*sizeof(int));CHKERRQ(ierr); 191 len = (new_nz - CHUNKSIZE - ai[row] - nrow - shift); 192 ierr = PetscMemcpy(new_j+ai[row]+shift+nrow+CHUNKSIZE,aj+ai[row]+shift+nrow,len*sizeof(int));CHKERRQ(ierr); 193 ierr = PetscMemcpy(new_a,aa,(ai[row]+nrow+shift)*sizeof(PetscScalar));CHKERRQ(ierr); 194 ierr = PetscMemcpy(new_a+ai[row]+shift+nrow+CHUNKSIZE,aa+ai[row]+shift+nrow,len*sizeof(PetscScalar));CHKERRQ(ierr); 195 /* free up old matrix storage */ 196 ierr = PetscFree(a->a);CHKERRQ(ierr); 197 if (!a->singlemalloc) { 198 ierr = PetscFree(a->i);CHKERRQ(ierr); 199 ierr = PetscFree(a->j);CHKERRQ(ierr); 200 } 201 aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j; 202 a->singlemalloc = PETSC_TRUE; 203 204 rp = aj + ai[row] + shift; ap = aa + ai[row] + shift; 205 rmax = imax[row] = imax[row] + CHUNKSIZE; 206 PetscLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + sizeof(PetscScalar))); 207 a->maxnz += CHUNKSIZE; 208 a->reallocs++; 209 } 210 N = nrow++ - 1; a->nz++; 211 /* shift up all the later entries in this row */ 212 for (ii=N; ii>=i; ii--) { 213 rp[ii+1] = rp[ii]; 214 ap[ii+1] = ap[ii]; 215 } 216 rp[i] = col; 217 ap[i] = value; 218 noinsert:; 219 low = i + 1; 220 } 221 ailen[row] = nrow; 222 } 223 PetscFunctionReturn(0); 224 } 225 226 #undef __FUNCT__ 227 #define __FUNCT__ "MatGetValues_SeqAIJ" 228 int MatGetValues_SeqAIJ(Mat A,int m,int *im,int n,int *in,PetscScalar *v) 229 { 230 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 231 int *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j; 232 int *ai = a->i,*ailen = a->ilen,shift = a->indexshift; 233 PetscScalar *ap,*aa = a->a,zero = 0.0; 234 235 PetscFunctionBegin; 236 for (k=0; k<m; k++) { /* loop over rows */ 237 row = im[k]; 238 if (row < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %d",row); 239 if (row >= A->m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: %d",row); 240 rp = aj + ai[row] + shift; ap = aa + ai[row] + shift; 241 nrow = ailen[row]; 242 for (l=0; l<n; l++) { /* loop over columns */ 243 if (in[l] < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %d",in[l]); 244 if (in[l] >= A->n) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: %d",in[l]); 245 col = in[l] - shift; 246 high = nrow; low = 0; /* assume unsorted */ 247 while (high-low > 5) { 248 t = (low+high)/2; 249 if (rp[t] > col) high = t; 250 else low = t; 251 } 252 for (i=low; i<high; i++) { 253 if (rp[i] > col) break; 254 if (rp[i] == col) { 255 *v++ = ap[i]; 256 goto finished; 257 } 258 } 259 *v++ = zero; 260 finished:; 261 } 262 } 263 PetscFunctionReturn(0); 264 } 265 266 267 #undef __FUNCT__ 268 #define __FUNCT__ "MatView_SeqAIJ_Binary" 269 int MatView_SeqAIJ_Binary(Mat A,PetscViewer viewer) 270 { 271 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 272 int i,fd,*col_lens,ierr; 273 274 PetscFunctionBegin; 275 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 276 ierr = PetscMalloc((4+A->m)*sizeof(int),&col_lens);CHKERRQ(ierr); 277 col_lens[0] = MAT_FILE_COOKIE; 278 col_lens[1] = A->m; 279 col_lens[2] = A->n; 280 col_lens[3] = a->nz; 281 282 /* store lengths of each row and write (including header) to file */ 283 for (i=0; i<A->m; i++) { 284 col_lens[4+i] = a->i[i+1] - a->i[i]; 285 } 286 ierr = PetscBinaryWrite(fd,col_lens,4+A->m,PETSC_INT,1);CHKERRQ(ierr); 287 ierr = PetscFree(col_lens);CHKERRQ(ierr); 288 289 /* store column indices (zero start index) */ 290 if (a->indexshift) { 291 for (i=0; i<a->nz; i++) a->j[i]--; 292 } 293 ierr = PetscBinaryWrite(fd,a->j,a->nz,PETSC_INT,0);CHKERRQ(ierr); 294 if (a->indexshift) { 295 for (i=0; i<a->nz; i++) a->j[i]++; 296 } 297 298 /* store nonzero values */ 299 ierr = PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,0);CHKERRQ(ierr); 300 PetscFunctionReturn(0); 301 } 302 303 extern int MatMPIAIJFactorInfo_SuperLu(Mat,PetscViewer); 304 extern int MatSeqAIJFactorInfo_Spooles(Mat,PetscViewer); 305 306 #undef __FUNCT__ 307 #define __FUNCT__ "MatView_SeqAIJ_ASCII" 308 int MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer) 309 { 310 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 311 int ierr,i,j,m = A->m,shift = a->indexshift; 312 char *name; 313 PetscViewerFormat format; 314 315 PetscFunctionBegin; 316 ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr); 317 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 318 if (format == PETSC_VIEWER_ASCII_INFO_LONG || format == PETSC_VIEWER_ASCII_INFO) { 319 if (a->inode.size) { 320 ierr = PetscViewerASCIIPrintf(viewer,"using I-node routines: found %d nodes, limit used is %d\n",a->inode.node_count,a->inode.limit);CHKERRQ(ierr); 321 } else { 322 ierr = PetscViewerASCIIPrintf(viewer,"not using I-node routines\n");CHKERRQ(ierr); 323 } 324 } else if (format == PETSC_VIEWER_ASCII_MATLAB) { 325 int nofinalvalue = 0; 326 if ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->n-!shift)) { 327 nofinalvalue = 1; 328 } 329 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 330 ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %d %d \n",m,A->n);CHKERRQ(ierr); 331 ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %d \n",a->nz);CHKERRQ(ierr); 332 ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%d,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr); 333 ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr); 334 335 for (i=0; i<m; i++) { 336 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 337 #if defined(PETSC_USE_COMPLEX) 338 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); 339 #else 340 ierr = PetscViewerASCIIPrintf(viewer,"%d %d %18.16e\n",i+1,a->j[j]+!shift,a->a[j]);CHKERRQ(ierr); 341 #endif 342 } 343 } 344 if (nofinalvalue) { 345 ierr = PetscViewerASCIIPrintf(viewer,"%d %d %18.16e\n",m,A->n,0.0);CHKERRQ(ierr); 346 } 347 ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr); 348 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 349 } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 350 #if defined(PETSC_HAVE_SUPERLUDIST) && !defined(PETSC_USE_SINGLE) && !defined(PETSC_USE_COMPLEX) 351 ierr = MatMPIAIJFactorInfo_SuperLu(A,viewer);CHKERRQ(ierr); 352 #endif 353 #if defined(PETSC_HAVE_SPOOLES) && !defined(PETSC_USE_SINGLE) && !defined(PETSC_USE_COMPLEX) 354 ierr = MatSeqAIJFactorInfo_Spooles(A,viewer);CHKERRQ(ierr); 355 #endif 356 PetscFunctionReturn(0); 357 } else if (format == PETSC_VIEWER_ASCII_COMMON) { 358 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 359 for (i=0; i<m; i++) { 360 ierr = PetscViewerASCIIPrintf(viewer,"row %d:",i);CHKERRQ(ierr); 361 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 362 #if defined(PETSC_USE_COMPLEX) 363 if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) { 364 ierr = PetscViewerASCIIPrintf(viewer," (%d, %g + %g i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 365 } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) { 366 ierr = PetscViewerASCIIPrintf(viewer," (%d, %g - %g i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 367 } else if (PetscRealPart(a->a[j]) != 0.0) { 368 ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr); 369 } 370 #else 371 if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);} 372 #endif 373 } 374 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 375 } 376 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 377 } else if (format == PETSC_VIEWER_ASCII_SYMMODU) { 378 int nzd=0,fshift=1,*sptr; 379 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 380 ierr = PetscMalloc((m+1)*sizeof(int),&sptr);CHKERRQ(ierr); 381 for (i=0; i<m; i++) { 382 sptr[i] = nzd+1; 383 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 384 if (a->j[j] >= i) { 385 #if defined(PETSC_USE_COMPLEX) 386 if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++; 387 #else 388 if (a->a[j] != 0.0) nzd++; 389 #endif 390 } 391 } 392 } 393 sptr[m] = nzd+1; 394 ierr = PetscViewerASCIIPrintf(viewer," %d %d\n\n",m,nzd);CHKERRQ(ierr); 395 for (i=0; i<m+1; i+=6) { 396 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);} 397 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);} 398 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);} 399 else if (i+1<m) {ierr = PetscViewerASCIIPrintf(viewer," %d %d %d\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);} 400 else if (i<m) {ierr = PetscViewerASCIIPrintf(viewer," %d %d\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);} 401 else {ierr = PetscViewerASCIIPrintf(viewer," %d\n",sptr[i]);CHKERRQ(ierr);} 402 } 403 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 404 ierr = PetscFree(sptr);CHKERRQ(ierr); 405 for (i=0; i<m; i++) { 406 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 407 if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %d ",a->j[j]+fshift);CHKERRQ(ierr);} 408 } 409 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 410 } 411 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 412 for (i=0; i<m; i++) { 413 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 414 if (a->j[j] >= i) { 415 #if defined(PETSC_USE_COMPLEX) 416 if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) { 417 ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 418 } 419 #else 420 if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",a->a[j]);CHKERRQ(ierr);} 421 #endif 422 } 423 } 424 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 425 } 426 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 427 } else if (format == PETSC_VIEWER_ASCII_DENSE) { 428 int cnt = 0,jcnt; 429 PetscScalar value; 430 431 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 432 for (i=0; i<m; i++) { 433 jcnt = 0; 434 for (j=0; j<A->n; j++) { 435 if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) { 436 value = a->a[cnt++]; 437 jcnt++; 438 } else { 439 value = 0.0; 440 } 441 #if defined(PETSC_USE_COMPLEX) 442 ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",PetscRealPart(value),PetscImaginaryPart(value));CHKERRQ(ierr); 443 #else 444 ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",value);CHKERRQ(ierr); 445 #endif 446 } 447 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 448 } 449 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 450 } else { 451 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 452 for (i=0; i<m; i++) { 453 ierr = PetscViewerASCIIPrintf(viewer,"row %d:",i);CHKERRQ(ierr); 454 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 455 #if defined(PETSC_USE_COMPLEX) 456 if (PetscImaginaryPart(a->a[j]) > 0.0) { 457 ierr = PetscViewerASCIIPrintf(viewer," (%d, %g + %g i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 458 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 459 ierr = PetscViewerASCIIPrintf(viewer," (%d, %g - %g i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 460 } else { 461 ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr); 462 } 463 #else 464 ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr); 465 #endif 466 } 467 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 468 } 469 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 470 } 471 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 472 PetscFunctionReturn(0); 473 } 474 475 #undef __FUNCT__ 476 #define __FUNCT__ "MatView_SeqAIJ_Draw_Zoom" 477 int MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa) 478 { 479 Mat A = (Mat) Aa; 480 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 481 int ierr,i,j,m = A->m,shift = a->indexshift,color; 482 PetscReal xl,yl,xr,yr,x_l,x_r,y_l,y_r,maxv = 0.0; 483 PetscViewer viewer; 484 PetscViewerFormat format; 485 486 PetscFunctionBegin; 487 ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr); 488 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 489 490 ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 491 /* loop over matrix elements drawing boxes */ 492 493 if (format != PETSC_VIEWER_DRAW_CONTOUR) { 494 /* Blue for negative, Cyan for zero and Red for positive */ 495 color = PETSC_DRAW_BLUE; 496 for (i=0; i<m; i++) { 497 y_l = m - i - 1.0; y_r = y_l + 1.0; 498 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 499 x_l = a->j[j] + shift; x_r = x_l + 1.0; 500 #if defined(PETSC_USE_COMPLEX) 501 if (PetscRealPart(a->a[j]) >= 0.) continue; 502 #else 503 if (a->a[j] >= 0.) continue; 504 #endif 505 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 506 } 507 } 508 color = PETSC_DRAW_CYAN; 509 for (i=0; i<m; i++) { 510 y_l = m - i - 1.0; y_r = y_l + 1.0; 511 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 512 x_l = a->j[j] + shift; x_r = x_l + 1.0; 513 if (a->a[j] != 0.) continue; 514 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 515 } 516 } 517 color = PETSC_DRAW_RED; 518 for (i=0; i<m; i++) { 519 y_l = m - i - 1.0; y_r = y_l + 1.0; 520 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 521 x_l = a->j[j] + shift; x_r = x_l + 1.0; 522 #if defined(PETSC_USE_COMPLEX) 523 if (PetscRealPart(a->a[j]) <= 0.) continue; 524 #else 525 if (a->a[j] <= 0.) continue; 526 #endif 527 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 528 } 529 } 530 } else { 531 /* use contour shading to indicate magnitude of values */ 532 /* first determine max of all nonzero values */ 533 int nz = a->nz,count; 534 PetscDraw popup; 535 PetscReal scale; 536 537 for (i=0; i<nz; i++) { 538 if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]); 539 } 540 scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/maxv; 541 ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr); 542 if (popup) {ierr = PetscDrawScalePopup(popup,0.0,maxv);CHKERRQ(ierr);} 543 count = 0; 544 for (i=0; i<m; i++) { 545 y_l = m - i - 1.0; y_r = y_l + 1.0; 546 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 547 x_l = a->j[j] + shift; x_r = x_l + 1.0; 548 color = PETSC_DRAW_BASIC_COLORS + (int)(scale*PetscAbsScalar(a->a[count])); 549 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 550 count++; 551 } 552 } 553 } 554 PetscFunctionReturn(0); 555 } 556 557 #undef __FUNCT__ 558 #define __FUNCT__ "MatView_SeqAIJ_Draw" 559 int MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer) 560 { 561 int ierr; 562 PetscDraw draw; 563 PetscReal xr,yr,xl,yl,h,w; 564 PetscTruth isnull; 565 566 PetscFunctionBegin; 567 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 568 ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); 569 if (isnull) PetscFunctionReturn(0); 570 571 ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr); 572 xr = A->n; yr = A->m; h = yr/10.0; w = xr/10.0; 573 xr += w; yr += h; xl = -w; yl = -h; 574 ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr); 575 ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr); 576 ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr); 577 PetscFunctionReturn(0); 578 } 579 580 #undef __FUNCT__ 581 #define __FUNCT__ "MatView_SeqAIJ" 582 int MatView_SeqAIJ(Mat A,PetscViewer viewer) 583 { 584 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 585 int ierr; 586 PetscTruth issocket,isascii,isbinary,isdraw; 587 588 PetscFunctionBegin; 589 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);CHKERRQ(ierr); 590 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr); 591 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);CHKERRQ(ierr); 592 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr); 593 if (issocket) { 594 if (a->indexshift) { 595 SETERRQ(1,"Can only socket send sparse matrix with 0 based indexing"); 596 } 597 ierr = PetscViewerSocketPutSparse_Private(viewer,A->m,A->n,a->nz,a->a,a->i,a->j);CHKERRQ(ierr); 598 } else if (isascii) { 599 ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr); 600 } else if (isbinary) { 601 ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr); 602 } else if (isdraw) { 603 ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr); 604 } else { 605 SETERRQ1(1,"Viewer type %s not supported by SeqAIJ matrices",((PetscObject)viewer)->type_name); 606 } 607 PetscFunctionReturn(0); 608 } 609 610 EXTERN int Mat_AIJ_CheckInode(Mat,PetscTruth); 611 EXTERN int MatUseSuperLU_DIST_MPIAIJ(Mat); 612 EXTERN int MatUseSpooles_SeqAIJ(Mat); 613 #undef __FUNCT__ 614 #define __FUNCT__ "MatAssemblyEnd_SeqAIJ" 615 int MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode) 616 { 617 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 618 int fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax,ierr; 619 int m = A->m,*ip,N,*ailen = a->ilen,shift = a->indexshift,rmax = 0; 620 PetscScalar *aa = a->a,*ap; 621 #if defined(PETSC_HAVE_SUPERLUDIST) || defined(PETSC_HAVE_SPOOLES) 622 PetscTruth flag; 623 #endif 624 625 PetscFunctionBegin; 626 if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 627 628 if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 629 for (i=1; i<m; i++) { 630 /* move each row back by the amount of empty slots (fshift) before it*/ 631 fshift += imax[i-1] - ailen[i-1]; 632 rmax = PetscMax(rmax,ailen[i]); 633 if (fshift) { 634 ip = aj + ai[i] + shift; 635 ap = aa + ai[i] + shift; 636 N = ailen[i]; 637 for (j=0; j<N; j++) { 638 ip[j-fshift] = ip[j]; 639 ap[j-fshift] = ap[j]; 640 } 641 } 642 ai[i] = ai[i-1] + ailen[i-1]; 643 } 644 if (m) { 645 fshift += imax[m-1] - ailen[m-1]; 646 ai[m] = ai[m-1] + ailen[m-1]; 647 } 648 /* reset ilen and imax for each row */ 649 for (i=0; i<m; i++) { 650 ailen[i] = imax[i] = ai[i+1] - ai[i]; 651 } 652 a->nz = ai[m] + shift; 653 654 /* diagonals may have moved, so kill the diagonal pointers */ 655 if (fshift && a->diag) { 656 ierr = PetscFree(a->diag);CHKERRQ(ierr); 657 PetscLogObjectMemory(A,-(m+1)*sizeof(int)); 658 a->diag = 0; 659 } 660 PetscLogInfo(A,"MatAssemblyEnd_SeqAIJ:Matrix size: %d X %d; storage space: %d unneeded,%d used\n",m,A->n,fshift,a->nz); 661 PetscLogInfo(A,"MatAssemblyEnd_SeqAIJ:Number of mallocs during MatSetValues() is %d\n",a->reallocs); 662 PetscLogInfo(A,"MatAssemblyEnd_SeqAIJ:Most nonzeros in any row is %d\n",rmax); 663 a->reallocs = 0; 664 A->info.nz_unneeded = (double)fshift; 665 a->rmax = rmax; 666 667 /* check out for identical nodes. If found, use inode functions */ 668 ierr = Mat_AIJ_CheckInode(A,(PetscTruth)(!fshift));CHKERRQ(ierr); 669 670 #if defined(PETSC_HAVE_SUPERLUDIST) 671 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_superlu_dist",&flag);CHKERRQ(ierr); 672 if (flag) { ierr = MatUseSuperLU_DIST_MPIAIJ(A);CHKERRQ(ierr); } 673 #endif 674 675 #if defined(PETSC_HAVE_SPOOLES) 676 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_spooles",&flag);CHKERRQ(ierr); 677 if (flag) { ierr = MatUseSpooles_SeqAIJ(A);CHKERRQ(ierr); } 678 #endif 679 680 PetscFunctionReturn(0); 681 } 682 683 #undef __FUNCT__ 684 #define __FUNCT__ "MatZeroEntries_SeqAIJ" 685 int MatZeroEntries_SeqAIJ(Mat A) 686 { 687 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 688 int ierr; 689 690 PetscFunctionBegin; 691 ierr = PetscMemzero(a->a,(a->i[A->m]+a->indexshift)*sizeof(PetscScalar));CHKERRQ(ierr); 692 PetscFunctionReturn(0); 693 } 694 695 #undef __FUNCT__ 696 #define __FUNCT__ "MatDestroy_SeqAIJ" 697 int MatDestroy_SeqAIJ(Mat A) 698 { 699 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 700 int ierr; 701 702 PetscFunctionBegin; 703 #if defined(PETSC_USE_LOG) 704 PetscLogObjectState((PetscObject)A,"Rows=%d, Cols=%d, NZ=%d",A->m,A->n,a->nz); 705 #endif 706 if (a->freedata) { 707 ierr = PetscFree(a->a);CHKERRQ(ierr); 708 if (!a->singlemalloc) { 709 ierr = PetscFree(a->i);CHKERRQ(ierr); 710 ierr = PetscFree(a->j);CHKERRQ(ierr); 711 } 712 } 713 if (a->row) { 714 ierr = ISDestroy(a->row);CHKERRQ(ierr); 715 } 716 if (a->col) { 717 ierr = ISDestroy(a->col);CHKERRQ(ierr); 718 } 719 if (a->diag) {ierr = PetscFree(a->diag);CHKERRQ(ierr);} 720 if (a->ilen) {ierr = PetscFree(a->ilen);CHKERRQ(ierr);} 721 if (a->imax) {ierr = PetscFree(a->imax);CHKERRQ(ierr);} 722 if (a->idiag) {ierr = PetscFree(a->idiag);CHKERRQ(ierr);} 723 if (a->solve_work) {ierr = PetscFree(a->solve_work);CHKERRQ(ierr);} 724 if (a->inode.size) {ierr = PetscFree(a->inode.size);CHKERRQ(ierr);} 725 if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);} 726 if (a->saved_values) {ierr = PetscFree(a->saved_values);CHKERRQ(ierr);} 727 if (a->coloring) {ierr = ISColoringDestroy(a->coloring);CHKERRQ(ierr);} 728 ierr = PetscFree(a);CHKERRQ(ierr); 729 PetscFunctionReturn(0); 730 } 731 732 #undef __FUNCT__ 733 #define __FUNCT__ "MatCompress_SeqAIJ" 734 int MatCompress_SeqAIJ(Mat A) 735 { 736 PetscFunctionBegin; 737 PetscFunctionReturn(0); 738 } 739 740 #undef __FUNCT__ 741 #define __FUNCT__ "MatSetOption_SeqAIJ" 742 int MatSetOption_SeqAIJ(Mat A,MatOption op) 743 { 744 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 745 746 PetscFunctionBegin; 747 switch (op) { 748 case MAT_ROW_ORIENTED: 749 a->roworiented = PETSC_TRUE; 750 break; 751 case MAT_KEEP_ZEROED_ROWS: 752 a->keepzeroedrows = PETSC_TRUE; 753 break; 754 case MAT_COLUMN_ORIENTED: 755 a->roworiented = PETSC_FALSE; 756 break; 757 case MAT_COLUMNS_SORTED: 758 a->sorted = PETSC_TRUE; 759 break; 760 case MAT_COLUMNS_UNSORTED: 761 a->sorted = PETSC_FALSE; 762 break; 763 case MAT_NO_NEW_NONZERO_LOCATIONS: 764 a->nonew = 1; 765 break; 766 case MAT_NEW_NONZERO_LOCATION_ERR: 767 a->nonew = -1; 768 break; 769 case MAT_NEW_NONZERO_ALLOCATION_ERR: 770 a->nonew = -2; 771 break; 772 case MAT_YES_NEW_NONZERO_LOCATIONS: 773 a->nonew = 0; 774 break; 775 case MAT_IGNORE_ZERO_ENTRIES: 776 a->ignorezeroentries = PETSC_TRUE; 777 break; 778 case MAT_USE_INODES: 779 a->inode.use = PETSC_TRUE; 780 break; 781 case MAT_DO_NOT_USE_INODES: 782 a->inode.use = PETSC_FALSE; 783 break; 784 case MAT_ROWS_SORTED: 785 case MAT_ROWS_UNSORTED: 786 case MAT_YES_NEW_DIAGONALS: 787 case MAT_IGNORE_OFF_PROC_ENTRIES: 788 case MAT_USE_HASH_TABLE: 789 case MAT_USE_SINGLE_PRECISION_SOLVES: 790 PetscLogInfo(A,"MatSetOption_SeqAIJ:Option ignored\n"); 791 break; 792 case MAT_NO_NEW_DIAGONALS: 793 SETERRQ(PETSC_ERR_SUP,"MAT_NO_NEW_DIAGONALS"); 794 case MAT_INODE_LIMIT_1: 795 a->inode.limit = 1; 796 break; 797 case MAT_INODE_LIMIT_2: 798 a->inode.limit = 2; 799 break; 800 case MAT_INODE_LIMIT_3: 801 a->inode.limit = 3; 802 break; 803 case MAT_INODE_LIMIT_4: 804 a->inode.limit = 4; 805 break; 806 case MAT_INODE_LIMIT_5: 807 a->inode.limit = 5; 808 break; 809 default: 810 SETERRQ(PETSC_ERR_SUP,"unknown option"); 811 } 812 PetscFunctionReturn(0); 813 } 814 815 #undef __FUNCT__ 816 #define __FUNCT__ "MatGetDiagonal_SeqAIJ" 817 int MatGetDiagonal_SeqAIJ(Mat A,Vec v) 818 { 819 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 820 int i,j,n,shift = a->indexshift,ierr; 821 PetscScalar *x,zero = 0.0; 822 823 PetscFunctionBegin; 824 ierr = VecSet(&zero,v);CHKERRQ(ierr); 825 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 826 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 827 if (n != A->m) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 828 for (i=0; i<A->m; i++) { 829 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 830 if (a->j[j]+shift == i) { 831 x[i] = a->a[j]; 832 break; 833 } 834 } 835 } 836 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 837 PetscFunctionReturn(0); 838 } 839 840 841 #undef __FUNCT__ 842 #define __FUNCT__ "MatMultTransposeAdd_SeqAIJ" 843 int MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy) 844 { 845 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 846 PetscScalar *x,*y; 847 int ierr,m = A->m,shift = a->indexshift; 848 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 849 PetscScalar *v,alpha; 850 int n,i,*idx; 851 #endif 852 853 PetscFunctionBegin; 854 if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);} 855 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 856 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 857 y = y + shift; /* shift for Fortran start by 1 indexing */ 858 859 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 860 fortranmulttransposeaddaij_(&m,x,a->i,a->j+shift,a->a+shift,y); 861 #else 862 for (i=0; i<m; i++) { 863 idx = a->j + a->i[i] + shift; 864 v = a->a + a->i[i] + shift; 865 n = a->i[i+1] - a->i[i]; 866 alpha = x[i]; 867 while (n-->0) {y[*idx++] += alpha * *v++;} 868 } 869 #endif 870 PetscLogFlops(2*a->nz); 871 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 872 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 873 PetscFunctionReturn(0); 874 } 875 876 #undef __FUNCT__ 877 #define __FUNCT__ "MatMultTranspose_SeqAIJ" 878 int MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy) 879 { 880 PetscScalar zero = 0.0; 881 int ierr; 882 883 PetscFunctionBegin; 884 ierr = VecSet(&zero,yy);CHKERRQ(ierr); 885 ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr); 886 PetscFunctionReturn(0); 887 } 888 889 890 #undef __FUNCT__ 891 #define __FUNCT__ "MatMult_SeqAIJ" 892 int MatMult_SeqAIJ(Mat A,Vec xx,Vec yy) 893 { 894 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 895 PetscScalar *x,*y,*v,sum; 896 int ierr,m = A->m,*idx,shift = a->indexshift,*ii; 897 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ) 898 int n,i,jrow,j; 899 #endif 900 901 #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 902 #pragma disjoint(*x,*y,*v) 903 #endif 904 905 PetscFunctionBegin; 906 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 907 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 908 x = x + shift; /* shift for Fortran start by 1 indexing */ 909 idx = a->j; 910 v = a->a; 911 ii = a->i; 912 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ) 913 fortranmultaij_(&m,x,ii,idx+shift,v+shift,y); 914 #else 915 v += shift; /* shift for Fortran start by 1 indexing */ 916 idx += shift; 917 for (i=0; i<m; i++) { 918 jrow = ii[i]; 919 n = ii[i+1] - jrow; 920 sum = 0.0; 921 for (j=0; j<n; j++) { 922 sum += v[jrow]*x[idx[jrow]]; jrow++; 923 } 924 y[i] = sum; 925 } 926 #endif 927 PetscLogFlops(2*a->nz - m); 928 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 929 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 930 PetscFunctionReturn(0); 931 } 932 933 #undef __FUNCT__ 934 #define __FUNCT__ "MatMultAdd_SeqAIJ" 935 int MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz) 936 { 937 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 938 PetscScalar *x,*y,*z,*v,sum; 939 int ierr,m = A->m,*idx,shift = a->indexshift,*ii; 940 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ) 941 int n,i,jrow,j; 942 #endif 943 944 PetscFunctionBegin; 945 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 946 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 947 if (zz != yy) { 948 ierr = VecGetArray(zz,&z);CHKERRQ(ierr); 949 } else { 950 z = y; 951 } 952 x = x + shift; /* shift for Fortran start by 1 indexing */ 953 idx = a->j; 954 v = a->a; 955 ii = a->i; 956 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ) 957 fortranmultaddaij_(&m,x,ii,idx+shift,v+shift,y,z); 958 #else 959 v += shift; /* shift for Fortran start by 1 indexing */ 960 idx += shift; 961 for (i=0; i<m; i++) { 962 jrow = ii[i]; 963 n = ii[i+1] - jrow; 964 sum = y[i]; 965 for (j=0; j<n; j++) { 966 sum += v[jrow]*x[idx[jrow]]; jrow++; 967 } 968 z[i] = sum; 969 } 970 #endif 971 PetscLogFlops(2*a->nz); 972 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 973 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 974 if (zz != yy) { 975 ierr = VecRestoreArray(zz,&z);CHKERRQ(ierr); 976 } 977 PetscFunctionReturn(0); 978 } 979 980 /* 981 Adds diagonal pointers to sparse matrix structure. 982 */ 983 #undef __FUNCT__ 984 #define __FUNCT__ "MatMarkDiagonal_SeqAIJ" 985 int MatMarkDiagonal_SeqAIJ(Mat A) 986 { 987 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 988 int i,j,*diag,m = A->m,shift = a->indexshift,ierr; 989 990 PetscFunctionBegin; 991 if (a->diag) PetscFunctionReturn(0); 992 993 ierr = PetscMalloc((m+1)*sizeof(int),&diag);CHKERRQ(ierr); 994 PetscLogObjectMemory(A,(m+1)*sizeof(int)); 995 for (i=0; i<A->m; i++) { 996 diag[i] = a->i[i+1]; 997 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 998 if (a->j[j]+shift == i) { 999 diag[i] = j - shift; 1000 break; 1001 } 1002 } 1003 } 1004 a->diag = diag; 1005 PetscFunctionReturn(0); 1006 } 1007 1008 /* 1009 Checks for missing diagonals 1010 */ 1011 #undef __FUNCT__ 1012 #define __FUNCT__ "MatMissingDiagonal_SeqAIJ" 1013 int MatMissingDiagonal_SeqAIJ(Mat A) 1014 { 1015 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1016 int *diag,*jj = a->j,i,shift = a->indexshift,ierr; 1017 1018 PetscFunctionBegin; 1019 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 1020 diag = a->diag; 1021 for (i=0; i<A->m; i++) { 1022 if (jj[diag[i]+shift] != i-shift) { 1023 SETERRQ1(1,"Matrix is missing diagonal number %d",i); 1024 } 1025 } 1026 PetscFunctionReturn(0); 1027 } 1028 1029 #undef __FUNCT__ 1030 #define __FUNCT__ "MatRelax_SeqAIJ" 1031 int MatRelax_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,int its,int lits,Vec xx) 1032 { 1033 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1034 PetscScalar *x,*b,*bs, d,*xs,sum,*v = a->a,*t=0,scale,*ts,*xb,*idiag=0; 1035 int ierr,*idx,*diag,n = A->n,m = A->m,i,shift = a->indexshift; 1036 1037 PetscFunctionBegin; 1038 its = its*lits; 1039 if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %d and local its %d both positive",its,lits); 1040 1041 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 1042 if (xx != bb) { 1043 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 1044 } else { 1045 b = x; 1046 } 1047 1048 if (!a->diag) {ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);} 1049 diag = a->diag; 1050 xs = x + shift; /* shifted by one for index start of a or a->j*/ 1051 if (flag == SOR_APPLY_UPPER) { 1052 /* apply (U + D/omega) to the vector */ 1053 bs = b + shift; 1054 for (i=0; i<m; i++) { 1055 d = fshift + a->a[diag[i] + shift]; 1056 n = a->i[i+1] - diag[i] - 1; 1057 PetscLogFlops(2*n-1); 1058 idx = a->j + diag[i] + (!shift); 1059 v = a->a + diag[i] + (!shift); 1060 sum = b[i]*d/omega; 1061 SPARSEDENSEDOT(sum,bs,v,idx,n); 1062 x[i] = sum; 1063 } 1064 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1065 if (bb != xx) {ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr);} 1066 PetscFunctionReturn(0); 1067 } 1068 1069 /* setup workspace for Eisenstat */ 1070 if (flag & SOR_EISENSTAT) { 1071 if (!a->idiag) { 1072 ierr = PetscMalloc(2*m*sizeof(PetscScalar),&a->idiag);CHKERRQ(ierr); 1073 a->ssor = a->idiag + m; 1074 v = a->a; 1075 for (i=0; i<m; i++) { a->idiag[i] = 1.0/v[diag[i]];} 1076 } 1077 t = a->ssor; 1078 idiag = a->idiag; 1079 } 1080 /* Let A = L + U + D; where L is lower trianglar, 1081 U is upper triangular, E is diagonal; This routine applies 1082 1083 (L + E)^{-1} A (U + E)^{-1} 1084 1085 to a vector efficiently using Eisenstat's trick. This is for 1086 the case of SSOR preconditioner, so E is D/omega where omega 1087 is the relaxation factor. 1088 */ 1089 1090 if (flag == SOR_APPLY_LOWER) { 1091 SETERRQ(PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented"); 1092 } else if ((flag & SOR_EISENSTAT) && omega == 1.0 && shift == 0 && fshift == 0.0) { 1093 /* special case for omega = 1.0 saves flops and some integer ops */ 1094 PetscScalar *v2; 1095 1096 v2 = a->a; 1097 /* x = (E + U)^{-1} b */ 1098 for (i=m-1; i>=0; i--) { 1099 n = a->i[i+1] - diag[i] - 1; 1100 idx = a->j + diag[i] + 1; 1101 v = a->a + diag[i] + 1; 1102 sum = b[i]; 1103 SPARSEDENSEMDOT(sum,xs,v,idx,n); 1104 x[i] = sum*idiag[i]; 1105 1106 /* t = b - (2*E - D)x */ 1107 t[i] = b[i] - (v2[diag[i]])*x[i]; 1108 } 1109 1110 /* t = (E + L)^{-1}t */ 1111 diag = a->diag; 1112 for (i=0; i<m; i++) { 1113 n = diag[i] - a->i[i]; 1114 idx = a->j + a->i[i]; 1115 v = a->a + a->i[i]; 1116 sum = t[i]; 1117 SPARSEDENSEMDOT(sum,t,v,idx,n); 1118 t[i] = sum*idiag[i]; 1119 1120 /* x = x + t */ 1121 x[i] += t[i]; 1122 } 1123 1124 PetscLogFlops(3*m-1 + 2*a->nz); 1125 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1126 if (bb != xx) {ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr);} 1127 PetscFunctionReturn(0); 1128 } else if (flag & SOR_EISENSTAT) { 1129 /* Let A = L + U + D; where L is lower trianglar, 1130 U is upper triangular, E is diagonal; This routine applies 1131 1132 (L + E)^{-1} A (U + E)^{-1} 1133 1134 to a vector efficiently using Eisenstat's trick. This is for 1135 the case of SSOR preconditioner, so E is D/omega where omega 1136 is the relaxation factor. 1137 */ 1138 scale = (2.0/omega) - 1.0; 1139 1140 /* x = (E + U)^{-1} b */ 1141 for (i=m-1; i>=0; i--) { 1142 d = fshift + a->a[diag[i] + shift]; 1143 n = a->i[i+1] - diag[i] - 1; 1144 idx = a->j + diag[i] + (!shift); 1145 v = a->a + diag[i] + (!shift); 1146 sum = b[i]; 1147 SPARSEDENSEMDOT(sum,xs,v,idx,n); 1148 x[i] = omega*(sum/d); 1149 } 1150 1151 /* t = b - (2*E - D)x */ 1152 v = a->a; 1153 for (i=0; i<m; i++) { t[i] = b[i] - scale*(v[*diag++ + shift])*x[i]; } 1154 1155 /* t = (E + L)^{-1}t */ 1156 ts = t + shift; /* shifted by one for index start of a or a->j*/ 1157 diag = a->diag; 1158 for (i=0; i<m; i++) { 1159 d = fshift + a->a[diag[i]+shift]; 1160 n = diag[i] - a->i[i]; 1161 idx = a->j + a->i[i] + shift; 1162 v = a->a + a->i[i] + shift; 1163 sum = t[i]; 1164 SPARSEDENSEMDOT(sum,ts,v,idx,n); 1165 t[i] = omega*(sum/d); 1166 /* x = x + t */ 1167 x[i] += t[i]; 1168 } 1169 1170 PetscLogFlops(6*m-1 + 2*a->nz); 1171 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1172 if (bb != xx) {ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr);} 1173 PetscFunctionReturn(0); 1174 } 1175 if (flag & SOR_ZERO_INITIAL_GUESS) { 1176 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 1177 #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ) 1178 fortranrelaxaijforwardzero_(&m,&omega,x,a->i,a->j,diag,a->a,b); 1179 #else 1180 for (i=0; i<m; i++) { 1181 d = fshift + a->a[diag[i]+shift]; 1182 n = diag[i] - a->i[i]; 1183 PetscLogFlops(2*n-1); 1184 idx = a->j + a->i[i] + shift; 1185 v = a->a + a->i[i] + shift; 1186 sum = b[i]; 1187 SPARSEDENSEMDOT(sum,xs,v,idx,n); 1188 x[i] = omega*(sum/d); 1189 } 1190 #endif 1191 xb = x; 1192 } else xb = b; 1193 if ((flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) && 1194 (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP)) { 1195 for (i=0; i<m; i++) { 1196 x[i] *= a->a[diag[i]+shift]; 1197 } 1198 PetscLogFlops(m); 1199 } 1200 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 1201 #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ) 1202 fortranrelaxaijbackwardzero_(&m,&omega,x,a->i,a->j,diag,a->a,xb); 1203 #else 1204 for (i=m-1; i>=0; i--) { 1205 d = fshift + a->a[diag[i] + shift]; 1206 n = a->i[i+1] - diag[i] - 1; 1207 PetscLogFlops(2*n-1); 1208 idx = a->j + diag[i] + (!shift); 1209 v = a->a + diag[i] + (!shift); 1210 sum = xb[i]; 1211 SPARSEDENSEMDOT(sum,xs,v,idx,n); 1212 x[i] = omega*(sum/d); 1213 } 1214 #endif 1215 } 1216 its--; 1217 } 1218 while (its--) { 1219 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 1220 #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ) 1221 fortranrelaxaijforward_(&m,&omega,x,a->i,a->j,diag,a->a,b); 1222 #else 1223 for (i=0; i<m; i++) { 1224 d = fshift + a->a[diag[i]+shift]; 1225 n = a->i[i+1] - a->i[i]; 1226 PetscLogFlops(2*n-1); 1227 idx = a->j + a->i[i] + shift; 1228 v = a->a + a->i[i] + shift; 1229 sum = b[i]; 1230 SPARSEDENSEMDOT(sum,xs,v,idx,n); 1231 x[i] = (1. - omega)*x[i] + omega*(sum + a->a[diag[i]+shift]*x[i])/d; 1232 } 1233 #endif 1234 } 1235 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 1236 #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ) 1237 fortranrelaxaijbackward_(&m,&omega,x,a->i,a->j,diag,a->a,b); 1238 #else 1239 for (i=m-1; i>=0; i--) { 1240 d = fshift + a->a[diag[i] + shift]; 1241 n = a->i[i+1] - a->i[i]; 1242 PetscLogFlops(2*n-1); 1243 idx = a->j + a->i[i] + shift; 1244 v = a->a + a->i[i] + shift; 1245 sum = b[i]; 1246 SPARSEDENSEMDOT(sum,xs,v,idx,n); 1247 x[i] = (1. - omega)*x[i] + omega*(sum + a->a[diag[i]+shift]*x[i])/d; 1248 } 1249 #endif 1250 } 1251 } 1252 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1253 if (bb != xx) {ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr);} 1254 PetscFunctionReturn(0); 1255 } 1256 1257 #undef __FUNCT__ 1258 #define __FUNCT__ "MatGetInfo_SeqAIJ" 1259 int MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info) 1260 { 1261 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1262 1263 PetscFunctionBegin; 1264 info->rows_global = (double)A->m; 1265 info->columns_global = (double)A->n; 1266 info->rows_local = (double)A->m; 1267 info->columns_local = (double)A->n; 1268 info->block_size = 1.0; 1269 info->nz_allocated = (double)a->maxnz; 1270 info->nz_used = (double)a->nz; 1271 info->nz_unneeded = (double)(a->maxnz - a->nz); 1272 info->assemblies = (double)A->num_ass; 1273 info->mallocs = (double)a->reallocs; 1274 info->memory = A->mem; 1275 if (A->factor) { 1276 info->fill_ratio_given = A->info.fill_ratio_given; 1277 info->fill_ratio_needed = A->info.fill_ratio_needed; 1278 info->factor_mallocs = A->info.factor_mallocs; 1279 } else { 1280 info->fill_ratio_given = 0; 1281 info->fill_ratio_needed = 0; 1282 info->factor_mallocs = 0; 1283 } 1284 PetscFunctionReturn(0); 1285 } 1286 1287 EXTERN int MatLUFactorSymbolic_SeqAIJ(Mat,IS,IS,MatLUInfo*,Mat*); 1288 EXTERN int MatLUFactorNumeric_SeqAIJ(Mat,Mat*); 1289 EXTERN int MatLUFactor_SeqAIJ(Mat,IS,IS,MatLUInfo*); 1290 EXTERN int MatSolve_SeqAIJ(Mat,Vec,Vec); 1291 EXTERN int MatSolveAdd_SeqAIJ(Mat,Vec,Vec,Vec); 1292 EXTERN int MatSolveTranspose_SeqAIJ(Mat,Vec,Vec); 1293 EXTERN int MatSolveTransposeAdd_SeqAIJ(Mat,Vec,Vec,Vec); 1294 1295 #undef __FUNCT__ 1296 #define __FUNCT__ "MatZeroRows_SeqAIJ" 1297 int MatZeroRows_SeqAIJ(Mat A,IS is,PetscScalar *diag) 1298 { 1299 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1300 int i,ierr,N,*rows,m = A->m - 1,shift = a->indexshift; 1301 1302 PetscFunctionBegin; 1303 ierr = ISGetLocalSize(is,&N);CHKERRQ(ierr); 1304 ierr = ISGetIndices(is,&rows);CHKERRQ(ierr); 1305 if (a->keepzeroedrows) { 1306 for (i=0; i<N; i++) { 1307 if (rows[i] < 0 || rows[i] > m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"row out of range"); 1308 ierr = PetscMemzero(&a->a[a->i[rows[i]]+shift],a->ilen[rows[i]]*sizeof(PetscScalar));CHKERRQ(ierr); 1309 } 1310 if (diag) { 1311 ierr = MatMissingDiagonal_SeqAIJ(A);CHKERRQ(ierr); 1312 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 1313 for (i=0; i<N; i++) { 1314 a->a[a->diag[rows[i]]] = *diag; 1315 } 1316 } 1317 } else { 1318 if (diag) { 1319 for (i=0; i<N; i++) { 1320 if (rows[i] < 0 || rows[i] > m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"row out of range"); 1321 if (a->ilen[rows[i]] > 0) { 1322 a->ilen[rows[i]] = 1; 1323 a->a[a->i[rows[i]]+shift] = *diag; 1324 a->j[a->i[rows[i]]+shift] = rows[i]+shift; 1325 } else { /* in case row was completely empty */ 1326 ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],diag,INSERT_VALUES);CHKERRQ(ierr); 1327 } 1328 } 1329 } else { 1330 for (i=0; i<N; i++) { 1331 if (rows[i] < 0 || rows[i] > m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"row out of range"); 1332 a->ilen[rows[i]] = 0; 1333 } 1334 } 1335 } 1336 ierr = ISRestoreIndices(is,&rows);CHKERRQ(ierr); 1337 ierr = MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1338 PetscFunctionReturn(0); 1339 } 1340 1341 #undef __FUNCT__ 1342 #define __FUNCT__ "MatGetRow_SeqAIJ" 1343 int MatGetRow_SeqAIJ(Mat A,int row,int *nz,int **idx,PetscScalar **v) 1344 { 1345 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1346 int *itmp,i,shift = a->indexshift,ierr; 1347 1348 PetscFunctionBegin; 1349 if (row < 0 || row >= A->m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Row %d out of range",row); 1350 1351 *nz = a->i[row+1] - a->i[row]; 1352 if (v) *v = a->a + a->i[row] + shift; 1353 if (idx) { 1354 itmp = a->j + a->i[row] + shift; 1355 if (*nz && shift) { 1356 ierr = PetscMalloc((*nz)*sizeof(int),idx);CHKERRQ(ierr); 1357 for (i=0; i<(*nz); i++) {(*idx)[i] = itmp[i] + shift;} 1358 } else if (*nz) { 1359 *idx = itmp; 1360 } 1361 else *idx = 0; 1362 } 1363 PetscFunctionReturn(0); 1364 } 1365 1366 #undef __FUNCT__ 1367 #define __FUNCT__ "MatRestoreRow_SeqAIJ" 1368 int MatRestoreRow_SeqAIJ(Mat A,int row,int *nz,int **idx,PetscScalar **v) 1369 { 1370 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1371 int ierr; 1372 1373 PetscFunctionBegin; 1374 if (idx) {if (*idx && a->indexshift) {ierr = PetscFree(*idx);CHKERRQ(ierr);}} 1375 PetscFunctionReturn(0); 1376 } 1377 1378 #undef __FUNCT__ 1379 #define __FUNCT__ "MatNorm_SeqAIJ" 1380 int MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm) 1381 { 1382 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1383 PetscScalar *v = a->a; 1384 PetscReal sum = 0.0; 1385 int i,j,shift = a->indexshift,ierr; 1386 1387 PetscFunctionBegin; 1388 if (type == NORM_FROBENIUS) { 1389 for (i=0; i<a->nz; i++) { 1390 #if defined(PETSC_USE_COMPLEX) 1391 sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 1392 #else 1393 sum += (*v)*(*v); v++; 1394 #endif 1395 } 1396 *nrm = sqrt(sum); 1397 } else if (type == NORM_1) { 1398 PetscReal *tmp; 1399 int *jj = a->j; 1400 ierr = PetscMalloc((A->n+1)*sizeof(PetscReal),&tmp);CHKERRQ(ierr); 1401 ierr = PetscMemzero(tmp,A->n*sizeof(PetscReal));CHKERRQ(ierr); 1402 *nrm = 0.0; 1403 for (j=0; j<a->nz; j++) { 1404 tmp[*jj++ + shift] += PetscAbsScalar(*v); v++; 1405 } 1406 for (j=0; j<A->n; j++) { 1407 if (tmp[j] > *nrm) *nrm = tmp[j]; 1408 } 1409 ierr = PetscFree(tmp);CHKERRQ(ierr); 1410 } else if (type == NORM_INFINITY) { 1411 *nrm = 0.0; 1412 for (j=0; j<A->m; j++) { 1413 v = a->a + a->i[j] + shift; 1414 sum = 0.0; 1415 for (i=0; i<a->i[j+1]-a->i[j]; i++) { 1416 sum += PetscAbsScalar(*v); v++; 1417 } 1418 if (sum > *nrm) *nrm = sum; 1419 } 1420 } else { 1421 SETERRQ(PETSC_ERR_SUP,"No support for two norm"); 1422 } 1423 PetscFunctionReturn(0); 1424 } 1425 1426 #undef __FUNCT__ 1427 #define __FUNCT__ "MatTranspose_SeqAIJ" 1428 int MatTranspose_SeqAIJ(Mat A,Mat *B) 1429 { 1430 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1431 Mat C; 1432 int i,ierr,*aj = a->j,*ai = a->i,m = A->m,len,*col; 1433 int shift = a->indexshift; 1434 PetscScalar *array = a->a; 1435 1436 PetscFunctionBegin; 1437 if (!B && m != A->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Square matrix only for in-place"); 1438 ierr = PetscMalloc((1+A->n)*sizeof(int),&col);CHKERRQ(ierr); 1439 ierr = PetscMemzero(col,(1+A->n)*sizeof(int));CHKERRQ(ierr); 1440 if (shift) { 1441 for (i=0; i<ai[m]-1; i++) aj[i] -= 1; 1442 } 1443 for (i=0; i<ai[m]+shift; i++) col[aj[i]] += 1; 1444 ierr = MatCreateSeqAIJ(A->comm,A->n,m,0,col,&C);CHKERRQ(ierr); 1445 ierr = PetscFree(col);CHKERRQ(ierr); 1446 for (i=0; i<m; i++) { 1447 len = ai[i+1]-ai[i]; 1448 ierr = MatSetValues(C,len,aj,1,&i,array,INSERT_VALUES);CHKERRQ(ierr); 1449 array += len; 1450 aj += len; 1451 } 1452 if (shift) { 1453 for (i=0; i<ai[m]-1; i++) aj[i] += 1; 1454 } 1455 1456 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1457 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1458 1459 if (B) { 1460 *B = C; 1461 } else { 1462 ierr = MatHeaderCopy(A,C);CHKERRQ(ierr); 1463 } 1464 PetscFunctionReturn(0); 1465 } 1466 1467 #undef __FUNCT__ 1468 #define __FUNCT__ "MatDiagonalScale_SeqAIJ" 1469 int MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr) 1470 { 1471 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1472 PetscScalar *l,*r,x,*v; 1473 int ierr,i,j,m = A->m,n = A->n,M,nz = a->nz,*jj,shift = a->indexshift; 1474 1475 PetscFunctionBegin; 1476 if (ll) { 1477 /* The local size is used so that VecMPI can be passed to this routine 1478 by MatDiagonalScale_MPIAIJ */ 1479 ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr); 1480 if (m != A->m) SETERRQ(PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length"); 1481 ierr = VecGetArray(ll,&l);CHKERRQ(ierr); 1482 v = a->a; 1483 for (i=0; i<m; i++) { 1484 x = l[i]; 1485 M = a->i[i+1] - a->i[i]; 1486 for (j=0; j<M; j++) { (*v++) *= x;} 1487 } 1488 ierr = VecRestoreArray(ll,&l);CHKERRQ(ierr); 1489 PetscLogFlops(nz); 1490 } 1491 if (rr) { 1492 ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr); 1493 if (n != A->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length"); 1494 ierr = VecGetArray(rr,&r);CHKERRQ(ierr); 1495 v = a->a; jj = a->j; 1496 for (i=0; i<nz; i++) { 1497 (*v++) *= r[*jj++ + shift]; 1498 } 1499 ierr = VecRestoreArray(rr,&r);CHKERRQ(ierr); 1500 PetscLogFlops(nz); 1501 } 1502 PetscFunctionReturn(0); 1503 } 1504 1505 #undef __FUNCT__ 1506 #define __FUNCT__ "MatGetSubMatrix_SeqAIJ" 1507 int MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,int csize,MatReuse scall,Mat *B) 1508 { 1509 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*c; 1510 int *smap,i,k,kstart,kend,ierr,oldcols = A->n,*lens; 1511 int row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi; 1512 int *irow,*icol,nrows,ncols,shift = a->indexshift,*ssmap; 1513 int *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen; 1514 PetscScalar *a_new,*mat_a; 1515 Mat C; 1516 PetscTruth stride; 1517 1518 PetscFunctionBegin; 1519 ierr = ISSorted(isrow,(PetscTruth*)&i);CHKERRQ(ierr); 1520 if (!i) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"ISrow is not sorted"); 1521 ierr = ISSorted(iscol,(PetscTruth*)&i);CHKERRQ(ierr); 1522 if (!i) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"IScol is not sorted"); 1523 1524 ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr); 1525 ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr); 1526 ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr); 1527 1528 ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr); 1529 ierr = ISStride(iscol,&stride);CHKERRQ(ierr); 1530 if (stride && step == 1) { 1531 /* special case of contiguous rows */ 1532 ierr = PetscMalloc((2*nrows+1)*sizeof(int),&lens);CHKERRQ(ierr); 1533 starts = lens + nrows; 1534 /* loop over new rows determining lens and starting points */ 1535 for (i=0; i<nrows; i++) { 1536 kstart = ai[irow[i]]+shift; 1537 kend = kstart + ailen[irow[i]]; 1538 for (k=kstart; k<kend; k++) { 1539 if (aj[k]+shift >= first) { 1540 starts[i] = k; 1541 break; 1542 } 1543 } 1544 sum = 0; 1545 while (k < kend) { 1546 if (aj[k++]+shift >= first+ncols) break; 1547 sum++; 1548 } 1549 lens[i] = sum; 1550 } 1551 /* create submatrix */ 1552 if (scall == MAT_REUSE_MATRIX) { 1553 int n_cols,n_rows; 1554 ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr); 1555 if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size"); 1556 ierr = MatZeroEntries(*B);CHKERRQ(ierr); 1557 C = *B; 1558 } else { 1559 ierr = MatCreateSeqAIJ(A->comm,nrows,ncols,0,lens,&C);CHKERRQ(ierr); 1560 } 1561 c = (Mat_SeqAIJ*)C->data; 1562 1563 /* loop over rows inserting into submatrix */ 1564 a_new = c->a; 1565 j_new = c->j; 1566 i_new = c->i; 1567 i_new[0] = -shift; 1568 for (i=0; i<nrows; i++) { 1569 ii = starts[i]; 1570 lensi = lens[i]; 1571 for (k=0; k<lensi; k++) { 1572 *j_new++ = aj[ii+k] - first; 1573 } 1574 ierr = PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(PetscScalar));CHKERRQ(ierr); 1575 a_new += lensi; 1576 i_new[i+1] = i_new[i] + lensi; 1577 c->ilen[i] = lensi; 1578 } 1579 ierr = PetscFree(lens);CHKERRQ(ierr); 1580 } else { 1581 ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr); 1582 ierr = PetscMalloc((1+oldcols)*sizeof(int),&smap);CHKERRQ(ierr); 1583 ssmap = smap + shift; 1584 ierr = PetscMalloc((1+nrows)*sizeof(int),&lens);CHKERRQ(ierr); 1585 ierr = PetscMemzero(smap,oldcols*sizeof(int));CHKERRQ(ierr); 1586 for (i=0; i<ncols; i++) smap[icol[i]] = i+1; 1587 /* determine lens of each row */ 1588 for (i=0; i<nrows; i++) { 1589 kstart = ai[irow[i]]+shift; 1590 kend = kstart + a->ilen[irow[i]]; 1591 lens[i] = 0; 1592 for (k=kstart; k<kend; k++) { 1593 if (ssmap[aj[k]]) { 1594 lens[i]++; 1595 } 1596 } 1597 } 1598 /* Create and fill new matrix */ 1599 if (scall == MAT_REUSE_MATRIX) { 1600 PetscTruth equal; 1601 1602 c = (Mat_SeqAIJ *)((*B)->data); 1603 if ((*B)->m != nrows || (*B)->n != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size"); 1604 ierr = PetscMemcmp(c->ilen,lens,(*B)->m*sizeof(int),&equal);CHKERRQ(ierr); 1605 if (!equal) { 1606 SETERRQ(PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros"); 1607 } 1608 ierr = PetscMemzero(c->ilen,(*B)->m*sizeof(int));CHKERRQ(ierr); 1609 C = *B; 1610 } else { 1611 ierr = MatCreateSeqAIJ(A->comm,nrows,ncols,0,lens,&C);CHKERRQ(ierr); 1612 } 1613 c = (Mat_SeqAIJ *)(C->data); 1614 for (i=0; i<nrows; i++) { 1615 row = irow[i]; 1616 kstart = ai[row]+shift; 1617 kend = kstart + a->ilen[row]; 1618 mat_i = c->i[i]+shift; 1619 mat_j = c->j + mat_i; 1620 mat_a = c->a + mat_i; 1621 mat_ilen = c->ilen + i; 1622 for (k=kstart; k<kend; k++) { 1623 if ((tcol=ssmap[a->j[k]])) { 1624 *mat_j++ = tcol - (!shift); 1625 *mat_a++ = a->a[k]; 1626 (*mat_ilen)++; 1627 1628 } 1629 } 1630 } 1631 /* Free work space */ 1632 ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr); 1633 ierr = PetscFree(smap);CHKERRQ(ierr); 1634 ierr = PetscFree(lens);CHKERRQ(ierr); 1635 } 1636 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1637 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1638 1639 ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr); 1640 *B = C; 1641 PetscFunctionReturn(0); 1642 } 1643 1644 /* 1645 */ 1646 #undef __FUNCT__ 1647 #define __FUNCT__ "MatILUFactor_SeqAIJ" 1648 int MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,MatILUInfo *info) 1649 { 1650 Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 1651 int ierr; 1652 Mat outA; 1653 PetscTruth row_identity,col_identity; 1654 1655 PetscFunctionBegin; 1656 if (info && info->levels != 0) SETERRQ(PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu"); 1657 ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr); 1658 ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr); 1659 if (!row_identity || !col_identity) { 1660 SETERRQ(1,"Row and column permutations must be identity for in-place ILU"); 1661 } 1662 1663 outA = inA; 1664 inA->factor = FACTOR_LU; 1665 a->row = row; 1666 a->col = col; 1667 ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr); 1668 ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr); 1669 1670 /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */ 1671 if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);} /* need to remove old one */ 1672 ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr); 1673 PetscLogObjectParent(inA,a->icol); 1674 1675 if (!a->solve_work) { /* this matrix may have been factored before */ 1676 ierr = PetscMalloc((inA->m+1)*sizeof(PetscScalar),&a->solve_work);CHKERRQ(ierr); 1677 } 1678 1679 if (!a->diag) { 1680 ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr); 1681 } 1682 ierr = MatLUFactorNumeric_SeqAIJ(inA,&outA);CHKERRQ(ierr); 1683 PetscFunctionReturn(0); 1684 } 1685 1686 #include "petscblaslapack.h" 1687 #undef __FUNCT__ 1688 #define __FUNCT__ "MatScale_SeqAIJ" 1689 int MatScale_SeqAIJ(PetscScalar *alpha,Mat inA) 1690 { 1691 Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 1692 int one = 1; 1693 1694 PetscFunctionBegin; 1695 BLscal_(&a->nz,alpha,a->a,&one); 1696 PetscLogFlops(a->nz); 1697 PetscFunctionReturn(0); 1698 } 1699 1700 #undef __FUNCT__ 1701 #define __FUNCT__ "MatGetSubMatrices_SeqAIJ" 1702 int MatGetSubMatrices_SeqAIJ(Mat A,int n,IS *irow,IS *icol,MatReuse scall,Mat **B) 1703 { 1704 int ierr,i; 1705 1706 PetscFunctionBegin; 1707 if (scall == MAT_INITIAL_MATRIX) { 1708 ierr = PetscMalloc((n+1)*sizeof(Mat),B);CHKERRQ(ierr); 1709 } 1710 1711 for (i=0; i<n; i++) { 1712 ierr = MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr); 1713 } 1714 PetscFunctionReturn(0); 1715 } 1716 1717 #undef __FUNCT__ 1718 #define __FUNCT__ "MatGetBlockSize_SeqAIJ" 1719 int MatGetBlockSize_SeqAIJ(Mat A,int *bs) 1720 { 1721 PetscFunctionBegin; 1722 *bs = 1; 1723 PetscFunctionReturn(0); 1724 } 1725 1726 #undef __FUNCT__ 1727 #define __FUNCT__ "MatIncreaseOverlap_SeqAIJ" 1728 int MatIncreaseOverlap_SeqAIJ(Mat A,int is_max,IS *is,int ov) 1729 { 1730 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1731 int shift,row,i,j,k,l,m,n,*idx,ierr,*nidx,isz,val; 1732 int start,end,*ai,*aj; 1733 PetscBT table; 1734 1735 PetscFunctionBegin; 1736 shift = a->indexshift; 1737 m = A->m; 1738 ai = a->i; 1739 aj = a->j+shift; 1740 1741 if (ov < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"illegal overlap value used"); 1742 1743 ierr = PetscMalloc((m+1)*sizeof(int),&nidx);CHKERRQ(ierr); 1744 ierr = PetscBTCreate(m,table);CHKERRQ(ierr); 1745 1746 for (i=0; i<is_max; i++) { 1747 /* Initialize the two local arrays */ 1748 isz = 0; 1749 ierr = PetscBTMemzero(m,table);CHKERRQ(ierr); 1750 1751 /* Extract the indices, assume there can be duplicate entries */ 1752 ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr); 1753 ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr); 1754 1755 /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 1756 for (j=0; j<n ; ++j){ 1757 if(!PetscBTLookupSet(table,idx[j])) { nidx[isz++] = idx[j];} 1758 } 1759 ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr); 1760 ierr = ISDestroy(is[i]);CHKERRQ(ierr); 1761 1762 k = 0; 1763 for (j=0; j<ov; j++){ /* for each overlap */ 1764 n = isz; 1765 for (; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */ 1766 row = nidx[k]; 1767 start = ai[row]; 1768 end = ai[row+1]; 1769 for (l = start; l<end ; l++){ 1770 val = aj[l] + shift; 1771 if (!PetscBTLookupSet(table,val)) {nidx[isz++] = val;} 1772 } 1773 } 1774 } 1775 ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,(is+i));CHKERRQ(ierr); 1776 } 1777 ierr = PetscBTDestroy(table);CHKERRQ(ierr); 1778 ierr = PetscFree(nidx);CHKERRQ(ierr); 1779 PetscFunctionReturn(0); 1780 } 1781 1782 /* -------------------------------------------------------------- */ 1783 #undef __FUNCT__ 1784 #define __FUNCT__ "MatPermute_SeqAIJ" 1785 int MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B) 1786 { 1787 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1788 PetscScalar *vwork; 1789 int i,ierr,nz,m = A->m,n = A->n,*cwork; 1790 int *row,*col,*cnew,j,*lens; 1791 IS icolp,irowp; 1792 1793 PetscFunctionBegin; 1794 ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr); 1795 ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr); 1796 ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr); 1797 ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr); 1798 1799 /* determine lengths of permuted rows */ 1800 ierr = PetscMalloc((m+1)*sizeof(int),&lens);CHKERRQ(ierr); 1801 for (i=0; i<m; i++) { 1802 lens[row[i]] = a->i[i+1] - a->i[i]; 1803 } 1804 ierr = MatCreateSeqAIJ(A->comm,m,n,0,lens,B);CHKERRQ(ierr); 1805 ierr = PetscFree(lens);CHKERRQ(ierr); 1806 1807 ierr = PetscMalloc(n*sizeof(int),&cnew);CHKERRQ(ierr); 1808 for (i=0; i<m; i++) { 1809 ierr = MatGetRow(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr); 1810 for (j=0; j<nz; j++) { cnew[j] = col[cwork[j]];} 1811 ierr = MatSetValues(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr); 1812 ierr = MatRestoreRow(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr); 1813 } 1814 ierr = PetscFree(cnew);CHKERRQ(ierr); 1815 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1816 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1817 ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr); 1818 ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr); 1819 ierr = ISDestroy(irowp);CHKERRQ(ierr); 1820 ierr = ISDestroy(icolp);CHKERRQ(ierr); 1821 PetscFunctionReturn(0); 1822 } 1823 1824 #undef __FUNCT__ 1825 #define __FUNCT__ "MatPrintHelp_SeqAIJ" 1826 int MatPrintHelp_SeqAIJ(Mat A) 1827 { 1828 static PetscTruth called = PETSC_FALSE; 1829 MPI_Comm comm = A->comm; 1830 int ierr; 1831 1832 PetscFunctionBegin; 1833 if (called) {PetscFunctionReturn(0);} else called = PETSC_TRUE; 1834 ierr = (*PetscHelpPrintf)(comm," Options for MATSEQAIJ and MATMPIAIJ matrix formats (the defaults):\n");CHKERRQ(ierr); 1835 ierr = (*PetscHelpPrintf)(comm," -mat_lu_pivotthreshold <threshold>: Set pivoting threshold\n");CHKERRQ(ierr); 1836 ierr = (*PetscHelpPrintf)(comm," -mat_aij_oneindex: internal indices begin at 1 instead of the default 0.\n");CHKERRQ(ierr); 1837 ierr = (*PetscHelpPrintf)(comm," -mat_aij_no_inode: Do not use inodes\n");CHKERRQ(ierr); 1838 ierr = (*PetscHelpPrintf)(comm," -mat_aij_inode_limit <limit>: Set inode limit (max limit=5)\n");CHKERRQ(ierr); 1839 #if defined(PETSC_HAVE_ESSL) 1840 ierr = (*PetscHelpPrintf)(comm," -mat_aij_essl: Use IBM sparse LU factorization and solve.\n");CHKERRQ(ierr); 1841 #endif 1842 #if defined(PETSC_HAVE_LUSOL) 1843 ierr = (*PetscHelpPrintf)(comm," -mat_aij_lusol: Use the Stanford LUSOL sparse factorization and solve.\n");CHKERRQ(ierr); 1844 #endif 1845 #if defined(PETSC_HAVE_MATLAB_ENGINE) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE) 1846 ierr = (*PetscHelpPrintf)(comm," -mat_aij_matlab: Use Matlab engine sparse LU factorization and solve.\n");CHKERRQ(ierr); 1847 #endif 1848 PetscFunctionReturn(0); 1849 } 1850 EXTERN int MatEqual_SeqAIJ(Mat A,Mat B,PetscTruth* flg); 1851 EXTERN int MatFDColoringCreate_SeqAIJ(Mat,ISColoring,MatFDColoring); 1852 EXTERN int MatILUDTFactor_SeqAIJ(Mat,MatILUInfo*,IS,IS,Mat*); 1853 #undef __FUNCT__ 1854 #define __FUNCT__ "MatCopy_SeqAIJ" 1855 int MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str) 1856 { 1857 int ierr; 1858 PetscTruth flg; 1859 1860 PetscFunctionBegin; 1861 ierr = PetscTypeCompare((PetscObject)B,MATSEQAIJ,&flg);CHKERRQ(ierr); 1862 if (str == SAME_NONZERO_PATTERN && flg) { 1863 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1864 Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 1865 1866 if (a->i[A->m]+a->indexshift != b->i[B->m]+a->indexshift) { 1867 SETERRQ(1,"Number of nonzeros in two matrices are different"); 1868 } 1869 ierr = PetscMemcpy(b->a,a->a,(a->i[A->m]+a->indexshift)*sizeof(PetscScalar));CHKERRQ(ierr); 1870 } else { 1871 ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr); 1872 } 1873 PetscFunctionReturn(0); 1874 } 1875 1876 #undef __FUNCT__ 1877 #define __FUNCT__ "MatSetUpPreallocation_SeqAIJ" 1878 int MatSetUpPreallocation_SeqAIJ(Mat A) 1879 { 1880 int ierr; 1881 1882 PetscFunctionBegin; 1883 ierr = MatSeqAIJSetPreallocation(A,PETSC_DEFAULT,0);CHKERRQ(ierr); 1884 PetscFunctionReturn(0); 1885 } 1886 1887 #undef __FUNCT__ 1888 #define __FUNCT__ "MatGetArray_SeqAIJ" 1889 int MatGetArray_SeqAIJ(Mat A,PetscScalar **array) 1890 { 1891 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1892 PetscFunctionBegin; 1893 *array = a->a; 1894 PetscFunctionReturn(0); 1895 } 1896 1897 #undef __FUNCT__ 1898 #define __FUNCT__ "MatRestoreArray_SeqAIJ" 1899 int MatRestoreArray_SeqAIJ(Mat A,PetscScalar **array) 1900 { 1901 PetscFunctionBegin; 1902 PetscFunctionReturn(0); 1903 } 1904 1905 #undef __FUNCT__ 1906 #define __FUNCT__ "MatFDColoringApply_SeqAIJ" 1907 int MatFDColoringApply_SeqAIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx) 1908 { 1909 int (*f)(void *,Vec,Vec,void*) = (int (*)(void *,Vec,Vec,void *))coloring->f; 1910 int k,ierr,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2; 1911 PetscScalar dx,mone = -1.0,*y,*xx,*w3_array; 1912 PetscScalar *vscale_array; 1913 PetscReal epsilon = coloring->error_rel,umin = coloring->umin; 1914 Vec w1,w2,w3; 1915 void *fctx = coloring->fctx; 1916 PetscTruth flg; 1917 1918 PetscFunctionBegin; 1919 if (!coloring->w1) { 1920 ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr); 1921 PetscLogObjectParent(coloring,coloring->w1); 1922 ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr); 1923 PetscLogObjectParent(coloring,coloring->w2); 1924 ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr); 1925 PetscLogObjectParent(coloring,coloring->w3); 1926 } 1927 w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3; 1928 1929 ierr = MatSetUnfactored(J);CHKERRQ(ierr); 1930 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr); 1931 if (flg) { 1932 PetscLogInfo(coloring,"MatFDColoringApply_SeqAIJ: Not calling MatZeroEntries()\n"); 1933 } else { 1934 ierr = MatZeroEntries(J);CHKERRQ(ierr); 1935 } 1936 1937 ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr); 1938 ierr = VecGetSize(x1,&N);CHKERRQ(ierr); 1939 1940 /* 1941 This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets 1942 coloring->F for the coarser grids from the finest 1943 */ 1944 if (coloring->F) { 1945 ierr = VecGetLocalSize(coloring->F,&m1);CHKERRQ(ierr); 1946 ierr = VecGetLocalSize(w1,&m2);CHKERRQ(ierr); 1947 if (m1 != m2) { 1948 coloring->F = 0; 1949 } 1950 } 1951 1952 if (coloring->F) { 1953 w1 = coloring->F; 1954 coloring->F = 0; 1955 } else { 1956 ierr = (*f)(sctx,x1,w1,fctx);CHKERRQ(ierr); 1957 } 1958 1959 /* 1960 Compute all the scale factors and share with other processors 1961 */ 1962 ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start; 1963 ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start; 1964 for (k=0; k<coloring->ncolors; k++) { 1965 /* 1966 Loop over each column associated with color adding the 1967 perturbation to the vector w3. 1968 */ 1969 for (l=0; l<coloring->ncolumns[k]; l++) { 1970 col = coloring->columns[k][l]; /* column of the matrix we are probing for */ 1971 dx = xx[col]; 1972 if (dx == 0.0) dx = 1.0; 1973 #if !defined(PETSC_USE_COMPLEX) 1974 if (dx < umin && dx >= 0.0) dx = umin; 1975 else if (dx < 0.0 && dx > -umin) dx = -umin; 1976 #else 1977 if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin; 1978 else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin; 1979 #endif 1980 dx *= epsilon; 1981 vscale_array[col] = 1.0/dx; 1982 } 1983 } 1984 vscale_array = vscale_array + start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 1985 ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1986 ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1987 1988 /* ierr = VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD); 1989 ierr = VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/ 1990 1991 if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow; 1992 else vscaleforrow = coloring->columnsforrow; 1993 1994 ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 1995 /* 1996 Loop over each color 1997 */ 1998 for (k=0; k<coloring->ncolors; k++) { 1999 ierr = VecCopy(x1,w3);CHKERRQ(ierr); 2000 ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start; 2001 /* 2002 Loop over each column associated with color adding the 2003 perturbation to the vector w3. 2004 */ 2005 for (l=0; l<coloring->ncolumns[k]; l++) { 2006 col = coloring->columns[k][l]; /* column of the matrix we are probing for */ 2007 dx = xx[col]; 2008 if (dx == 0.0) dx = 1.0; 2009 #if !defined(PETSC_USE_COMPLEX) 2010 if (dx < umin && dx >= 0.0) dx = umin; 2011 else if (dx < 0.0 && dx > -umin) dx = -umin; 2012 #else 2013 if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin; 2014 else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin; 2015 #endif 2016 dx *= epsilon; 2017 if (!PetscAbsScalar(dx)) SETERRQ(1,"Computed 0 differencing parameter"); 2018 w3_array[col] += dx; 2019 } 2020 w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr); 2021 2022 /* 2023 Evaluate function at x1 + dx (here dx is a vector of perturbations) 2024 */ 2025 2026 ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr); 2027 ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr); 2028 2029 /* 2030 Loop over rows of vector, putting results into Jacobian matrix 2031 */ 2032 ierr = VecGetArray(w2,&y);CHKERRQ(ierr); 2033 for (l=0; l<coloring->nrows[k]; l++) { 2034 row = coloring->rows[k][l]; 2035 col = coloring->columnsforrow[k][l]; 2036 y[row] *= vscale_array[vscaleforrow[k][l]]; 2037 srow = row + start; 2038 ierr = MatSetValues_SeqAIJ(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr); 2039 } 2040 ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr); 2041 } 2042 ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 2043 xx = xx + start; ierr = VecRestoreArray(x1,&xx);CHKERRQ(ierr); 2044 ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2045 ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2046 PetscFunctionReturn(0); 2047 } 2048 2049 #include "petscblaslapack.h" 2050 2051 #undef __FUNCT__ 2052 #define __FUNCT__ "MatAXPY_SeqAIJ" 2053 int MatAXPY_SeqAIJ(PetscScalar *a,Mat X,Mat Y,MatStructure str) 2054 { 2055 int ierr,one=1; 2056 Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data,*y = (Mat_SeqAIJ *)Y->data; 2057 2058 PetscFunctionBegin; 2059 if (str == SAME_NONZERO_PATTERN) { 2060 BLaxpy_(&x->nz,a,x->a,&one,y->a,&one); 2061 } else { 2062 ierr = MatAXPY_Basic(a,X,Y,str);CHKERRQ(ierr); 2063 } 2064 PetscFunctionReturn(0); 2065 } 2066 2067 2068 /* -------------------------------------------------------------------*/ 2069 static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ, 2070 MatGetRow_SeqAIJ, 2071 MatRestoreRow_SeqAIJ, 2072 MatMult_SeqAIJ, 2073 MatMultAdd_SeqAIJ, 2074 MatMultTranspose_SeqAIJ, 2075 MatMultTransposeAdd_SeqAIJ, 2076 MatSolve_SeqAIJ, 2077 MatSolveAdd_SeqAIJ, 2078 MatSolveTranspose_SeqAIJ, 2079 MatSolveTransposeAdd_SeqAIJ, 2080 MatLUFactor_SeqAIJ, 2081 0, 2082 MatRelax_SeqAIJ, 2083 MatTranspose_SeqAIJ, 2084 MatGetInfo_SeqAIJ, 2085 MatEqual_SeqAIJ, 2086 MatGetDiagonal_SeqAIJ, 2087 MatDiagonalScale_SeqAIJ, 2088 MatNorm_SeqAIJ, 2089 0, 2090 MatAssemblyEnd_SeqAIJ, 2091 MatCompress_SeqAIJ, 2092 MatSetOption_SeqAIJ, 2093 MatZeroEntries_SeqAIJ, 2094 MatZeroRows_SeqAIJ, 2095 MatLUFactorSymbolic_SeqAIJ, 2096 MatLUFactorNumeric_SeqAIJ, 2097 0, 2098 0, 2099 MatSetUpPreallocation_SeqAIJ, 2100 MatILUFactorSymbolic_SeqAIJ, 2101 0, 2102 MatGetArray_SeqAIJ, 2103 MatRestoreArray_SeqAIJ, 2104 MatDuplicate_SeqAIJ, 2105 0, 2106 0, 2107 MatILUFactor_SeqAIJ, 2108 0, 2109 MatAXPY_SeqAIJ, 2110 MatGetSubMatrices_SeqAIJ, 2111 MatIncreaseOverlap_SeqAIJ, 2112 MatGetValues_SeqAIJ, 2113 MatCopy_SeqAIJ, 2114 MatPrintHelp_SeqAIJ, 2115 MatScale_SeqAIJ, 2116 0, 2117 0, 2118 MatILUDTFactor_SeqAIJ, 2119 MatGetBlockSize_SeqAIJ, 2120 MatGetRowIJ_SeqAIJ, 2121 MatRestoreRowIJ_SeqAIJ, 2122 MatGetColumnIJ_SeqAIJ, 2123 MatRestoreColumnIJ_SeqAIJ, 2124 MatFDColoringCreate_SeqAIJ, 2125 0, 2126 0, 2127 MatPermute_SeqAIJ, 2128 0, 2129 0, 2130 MatDestroy_SeqAIJ, 2131 MatView_SeqAIJ, 2132 MatGetPetscMaps_Petsc, 2133 0, 2134 0, 2135 0, 2136 0, 2137 0, 2138 0, 2139 0, 2140 0, 2141 MatSetColoring_SeqAIJ, 2142 MatSetValuesAdic_SeqAIJ, 2143 MatSetValuesAdifor_SeqAIJ, 2144 MatFDColoringApply_SeqAIJ}; 2145 2146 EXTERN int MatUseSuperLU_SeqAIJ(Mat); 2147 EXTERN int MatUseEssl_SeqAIJ(Mat); 2148 EXTERN int MatUseLUSOL_SeqAIJ(Mat); 2149 EXTERN int MatUseMatlab_SeqAIJ(Mat); 2150 EXTERN int MatUseDXML_SeqAIJ(Mat); 2151 2152 EXTERN_C_BEGIN 2153 #undef __FUNCT__ 2154 #define __FUNCT__ "MatSeqAIJSetColumnIndices_SeqAIJ" 2155 2156 int MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,int *indices) 2157 { 2158 Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2159 int i,nz,n; 2160 2161 PetscFunctionBegin; 2162 2163 nz = aij->maxnz; 2164 n = mat->n; 2165 for (i=0; i<nz; i++) { 2166 aij->j[i] = indices[i]; 2167 } 2168 aij->nz = nz; 2169 for (i=0; i<n; i++) { 2170 aij->ilen[i] = aij->imax[i]; 2171 } 2172 2173 PetscFunctionReturn(0); 2174 } 2175 EXTERN_C_END 2176 2177 #undef __FUNCT__ 2178 #define __FUNCT__ "MatSeqAIJSetColumnIndices" 2179 /*@ 2180 MatSeqAIJSetColumnIndices - Set the column indices for all the rows 2181 in the matrix. 2182 2183 Input Parameters: 2184 + mat - the SeqAIJ matrix 2185 - indices - the column indices 2186 2187 Level: advanced 2188 2189 Notes: 2190 This can be called if you have precomputed the nonzero structure of the 2191 matrix and want to provide it to the matrix object to improve the performance 2192 of the MatSetValues() operation. 2193 2194 You MUST have set the correct numbers of nonzeros per row in the call to 2195 MatCreateSeqAIJ(). 2196 2197 MUST be called before any calls to MatSetValues(); 2198 2199 The indices should start with zero, not one. 2200 2201 @*/ 2202 int MatSeqAIJSetColumnIndices(Mat mat,int *indices) 2203 { 2204 int ierr,(*f)(Mat,int *); 2205 2206 PetscFunctionBegin; 2207 PetscValidHeaderSpecific(mat,MAT_COOKIE); 2208 ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqAIJSetColumnIndices_C",(void (**)(void))&f);CHKERRQ(ierr); 2209 if (f) { 2210 ierr = (*f)(mat,indices);CHKERRQ(ierr); 2211 } else { 2212 SETERRQ(1,"Wrong type of matrix to set column indices"); 2213 } 2214 PetscFunctionReturn(0); 2215 } 2216 2217 /* ----------------------------------------------------------------------------------------*/ 2218 2219 EXTERN_C_BEGIN 2220 #undef __FUNCT__ 2221 #define __FUNCT__ "MatStoreValues_SeqAIJ" 2222 int MatStoreValues_SeqAIJ(Mat mat) 2223 { 2224 Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2225 int nz = aij->i[mat->m]+aij->indexshift,ierr; 2226 2227 PetscFunctionBegin; 2228 if (aij->nonew != 1) { 2229 SETERRQ(1,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first"); 2230 } 2231 2232 /* allocate space for values if not already there */ 2233 if (!aij->saved_values) { 2234 ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr); 2235 } 2236 2237 /* copy values over */ 2238 ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr); 2239 PetscFunctionReturn(0); 2240 } 2241 EXTERN_C_END 2242 2243 #undef __FUNCT__ 2244 #define __FUNCT__ "MatStoreValues" 2245 /*@ 2246 MatStoreValues - Stashes a copy of the matrix values; this allows, for 2247 example, reuse of the linear part of a Jacobian, while recomputing the 2248 nonlinear portion. 2249 2250 Collect on Mat 2251 2252 Input Parameters: 2253 . mat - the matrix (currently on AIJ matrices support this option) 2254 2255 Level: advanced 2256 2257 Common Usage, with SNESSolve(): 2258 $ Create Jacobian matrix 2259 $ Set linear terms into matrix 2260 $ Apply boundary conditions to matrix, at this time matrix must have 2261 $ final nonzero structure (i.e. setting the nonlinear terms and applying 2262 $ boundary conditions again will not change the nonzero structure 2263 $ ierr = MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS); 2264 $ ierr = MatStoreValues(mat); 2265 $ Call SNESSetJacobian() with matrix 2266 $ In your Jacobian routine 2267 $ ierr = MatRetrieveValues(mat); 2268 $ Set nonlinear terms in matrix 2269 2270 Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself: 2271 $ // build linear portion of Jacobian 2272 $ ierr = MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS); 2273 $ ierr = MatStoreValues(mat); 2274 $ loop over nonlinear iterations 2275 $ ierr = MatRetrieveValues(mat); 2276 $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian 2277 $ // call MatAssemblyBegin/End() on matrix 2278 $ Solve linear system with Jacobian 2279 $ endloop 2280 2281 Notes: 2282 Matrix must already be assemblied before calling this routine 2283 Must set the matrix option MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS); before 2284 calling this routine. 2285 2286 .seealso: MatRetrieveValues() 2287 2288 @*/ 2289 int MatStoreValues(Mat mat) 2290 { 2291 int ierr,(*f)(Mat); 2292 2293 PetscFunctionBegin; 2294 PetscValidHeaderSpecific(mat,MAT_COOKIE); 2295 if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 2296 if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2297 2298 ierr = PetscObjectQueryFunction((PetscObject)mat,"MatStoreValues_C",(void (**)(void))&f);CHKERRQ(ierr); 2299 if (f) { 2300 ierr = (*f)(mat);CHKERRQ(ierr); 2301 } else { 2302 SETERRQ(1,"Wrong type of matrix to store values"); 2303 } 2304 PetscFunctionReturn(0); 2305 } 2306 2307 EXTERN_C_BEGIN 2308 #undef __FUNCT__ 2309 #define __FUNCT__ "MatRetrieveValues_SeqAIJ" 2310 int MatRetrieveValues_SeqAIJ(Mat mat) 2311 { 2312 Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2313 int nz = aij->i[mat->m]+aij->indexshift,ierr; 2314 2315 PetscFunctionBegin; 2316 if (aij->nonew != 1) { 2317 SETERRQ(1,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first"); 2318 } 2319 if (!aij->saved_values) { 2320 SETERRQ(1,"Must call MatStoreValues(A);first"); 2321 } 2322 2323 /* copy values over */ 2324 ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr); 2325 PetscFunctionReturn(0); 2326 } 2327 EXTERN_C_END 2328 2329 #undef __FUNCT__ 2330 #define __FUNCT__ "MatRetrieveValues" 2331 /*@ 2332 MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 2333 example, reuse of the linear part of a Jacobian, while recomputing the 2334 nonlinear portion. 2335 2336 Collect on Mat 2337 2338 Input Parameters: 2339 . mat - the matrix (currently on AIJ matrices support this option) 2340 2341 Level: advanced 2342 2343 .seealso: MatStoreValues() 2344 2345 @*/ 2346 int MatRetrieveValues(Mat mat) 2347 { 2348 int ierr,(*f)(Mat); 2349 2350 PetscFunctionBegin; 2351 PetscValidHeaderSpecific(mat,MAT_COOKIE); 2352 if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 2353 if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2354 2355 ierr = PetscObjectQueryFunction((PetscObject)mat,"MatRetrieveValues_C",(void (**)(void))&f);CHKERRQ(ierr); 2356 if (f) { 2357 ierr = (*f)(mat);CHKERRQ(ierr); 2358 } else { 2359 SETERRQ(1,"Wrong type of matrix to retrieve values"); 2360 } 2361 PetscFunctionReturn(0); 2362 } 2363 2364 /* 2365 This allows SeqAIJ matrices to be passed to the matlab engine 2366 */ 2367 #if defined(PETSC_HAVE_MATLAB_ENGINE) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE) 2368 #include "engine.h" /* Matlab include file */ 2369 #include "mex.h" /* Matlab include file */ 2370 EXTERN_C_BEGIN 2371 #undef __FUNCT__ 2372 #define __FUNCT__ "MatMatlabEnginePut_SeqAIJ" 2373 int MatMatlabEnginePut_SeqAIJ(PetscObject obj,void *engine) 2374 { 2375 int ierr,i,*ai,*aj; 2376 Mat B = (Mat)obj; 2377 PetscScalar *array; 2378 mxArray *mat; 2379 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)B->data; 2380 2381 PetscFunctionBegin; 2382 mat = mxCreateSparse(B->n,B->m,aij->nz,mxREAL); 2383 ierr = PetscMemcpy(mxGetPr(mat),aij->a,aij->nz*sizeof(PetscScalar));CHKERRQ(ierr); 2384 /* Matlab stores by column, not row so we pass in the transpose of the matrix */ 2385 ierr = PetscMemcpy(mxGetIr(mat),aij->j,aij->nz*sizeof(int));CHKERRQ(ierr); 2386 ierr = PetscMemcpy(mxGetJc(mat),aij->i,(B->m+1)*sizeof(int));CHKERRQ(ierr); 2387 2388 /* Matlab indices start at 0 for sparse (what a surprise) */ 2389 if (aij->indexshift) { 2390 for (i=0; i<B->m+1; i++) { 2391 ai[i]--; 2392 } 2393 for (i=0; i<aij->nz; i++) { 2394 aj[i]--; 2395 } 2396 } 2397 ierr = PetscObjectName(obj);CHKERRQ(ierr); 2398 mxSetName(mat,obj->name); 2399 engPutArray((Engine *)engine,mat); 2400 PetscFunctionReturn(0); 2401 } 2402 EXTERN_C_END 2403 2404 EXTERN_C_BEGIN 2405 #undef __FUNCT__ 2406 #define __FUNCT__ "MatMatlabEngineGet_SeqAIJ" 2407 int MatMatlabEngineGet_SeqAIJ(PetscObject obj,void *engine) 2408 { 2409 int ierr,ii; 2410 Mat mat = (Mat)obj; 2411 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 2412 mxArray *mmat; 2413 2414 PetscFunctionBegin; 2415 ierr = PetscFree(aij->a);CHKERRQ(ierr); 2416 aij->indexshift = 0; 2417 2418 mmat = engGetArray((Engine *)engine,obj->name); 2419 2420 aij->nz = (mxGetJc(mmat))[mat->m]; 2421 ierr = PetscMalloc(aij->nz*(sizeof(int)+sizeof(PetscScalar))+(mat->m+1)*sizeof(int),&aij->a);CHKERRQ(ierr); 2422 aij->j = (int*)(aij->a + aij->nz); 2423 aij->i = aij->j + aij->nz; 2424 aij->singlemalloc = PETSC_TRUE; 2425 aij->freedata = PETSC_TRUE; 2426 2427 ierr = PetscMemcpy(aij->a,mxGetPr(mmat),aij->nz*sizeof(PetscScalar));CHKERRQ(ierr); 2428 /* Matlab stores by column, not row so we pass in the transpose of the matrix */ 2429 ierr = PetscMemcpy(aij->j,mxGetIr(mmat),aij->nz*sizeof(int));CHKERRQ(ierr); 2430 ierr = PetscMemcpy(aij->i,mxGetJc(mmat),(mat->m+1)*sizeof(int));CHKERRQ(ierr); 2431 2432 for (ii=0; ii<mat->m; ii++) { 2433 aij->ilen[ii] = aij->imax[ii] = aij->i[ii+1] - aij->i[ii]; 2434 } 2435 2436 ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2437 ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2438 2439 PetscFunctionReturn(0); 2440 } 2441 EXTERN_C_END 2442 #endif 2443 2444 /* --------------------------------------------------------------------------------*/ 2445 #define SKIP_ALLOCATION -4 2446 2447 #undef __FUNCT__ 2448 #define __FUNCT__ "MatCreateSeqAIJ" 2449 /*@C 2450 MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format 2451 (the default parallel PETSc format). For good matrix assembly performance 2452 the user should preallocate the matrix storage by setting the parameter nz 2453 (or the array nnz). By setting these parameters accurately, performance 2454 during matrix assembly can be increased by more than a factor of 50. 2455 2456 Collective on MPI_Comm 2457 2458 Input Parameters: 2459 + comm - MPI communicator, set to PETSC_COMM_SELF 2460 . m - number of rows 2461 . n - number of columns 2462 . nz - number of nonzeros per row (same for all rows) 2463 - nnz - array containing the number of nonzeros in the various rows 2464 (possibly different for each row) or PETSC_NULL 2465 2466 Output Parameter: 2467 . A - the matrix 2468 2469 Notes: 2470 The AIJ format (also called the Yale sparse matrix format or 2471 compressed row storage), is fully compatible with standard Fortran 77 2472 storage. That is, the stored row and column indices can begin at 2473 either one (as in Fortran) or zero. See the users' manual for details. 2474 2475 Specify the preallocated storage with either nz or nnz (not both). 2476 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 2477 allocation. For large problems you MUST preallocate memory or you 2478 will get TERRIBLE performance, see the users' manual chapter on matrices. 2479 2480 By default, this format uses inodes (identical nodes) when possible, to 2481 improve numerical efficiency of matrix-vector products and solves. We 2482 search for consecutive rows with the same nonzero structure, thereby 2483 reusing matrix information to achieve increased efficiency. 2484 2485 Options Database Keys: 2486 + -mat_aij_no_inode - Do not use inodes 2487 . -mat_aij_inode_limit <limit> - Sets inode limit (max limit=5) 2488 - -mat_aij_oneindex - Internally use indexing starting at 1 2489 rather than 0. Note that when calling MatSetValues(), 2490 the user still MUST index entries starting at 0! 2491 2492 Level: intermediate 2493 2494 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays() 2495 2496 @*/ 2497 int MatCreateSeqAIJ(MPI_Comm comm,int m,int n,int nz,int *nnz,Mat *A) 2498 { 2499 int ierr; 2500 2501 PetscFunctionBegin; 2502 ierr = MatCreate(comm,m,n,m,n,A);CHKERRQ(ierr); 2503 ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr); 2504 ierr = MatSeqAIJSetPreallocation(*A,nz,nnz);CHKERRQ(ierr); 2505 PetscFunctionReturn(0); 2506 } 2507 2508 #undef __FUNCT__ 2509 #define __FUNCT__ "MatSeqAIJSetPreallocation" 2510 /*@C 2511 MatSeqAIJSetPreallocation - For good matrix assembly performance 2512 the user should preallocate the matrix storage by setting the parameter nz 2513 (or the array nnz). By setting these parameters accurately, performance 2514 during matrix assembly can be increased by more than a factor of 50. 2515 2516 Collective on MPI_Comm 2517 2518 Input Parameters: 2519 + comm - MPI communicator, set to PETSC_COMM_SELF 2520 . m - number of rows 2521 . n - number of columns 2522 . nz - number of nonzeros per row (same for all rows) 2523 - nnz - array containing the number of nonzeros in the various rows 2524 (possibly different for each row) or PETSC_NULL 2525 2526 Output Parameter: 2527 . A - the matrix 2528 2529 Notes: 2530 The AIJ format (also called the Yale sparse matrix format or 2531 compressed row storage), is fully compatible with standard Fortran 77 2532 storage. That is, the stored row and column indices can begin at 2533 either one (as in Fortran) or zero. See the users' manual for details. 2534 2535 Specify the preallocated storage with either nz or nnz (not both). 2536 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 2537 allocation. For large problems you MUST preallocate memory or you 2538 will get TERRIBLE performance, see the users' manual chapter on matrices. 2539 2540 By default, this format uses inodes (identical nodes) when possible, to 2541 improve numerical efficiency of matrix-vector products and solves. We 2542 search for consecutive rows with the same nonzero structure, thereby 2543 reusing matrix information to achieve increased efficiency. 2544 2545 Options Database Keys: 2546 + -mat_aij_no_inode - Do not use inodes 2547 . -mat_aij_inode_limit <limit> - Sets inode limit (max limit=5) 2548 - -mat_aij_oneindex - Internally use indexing starting at 1 2549 rather than 0. Note that when calling MatSetValues(), 2550 the user still MUST index entries starting at 0! 2551 2552 Level: intermediate 2553 2554 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays() 2555 2556 @*/ 2557 int MatSeqAIJSetPreallocation(Mat B,int nz,int *nnz) 2558 { 2559 Mat_SeqAIJ *b; 2560 int i,len,ierr; 2561 PetscTruth flg2,skipallocation = PETSC_FALSE; 2562 2563 PetscFunctionBegin; 2564 ierr = PetscTypeCompare((PetscObject)B,MATSEQAIJ,&flg2);CHKERRQ(ierr); 2565 if (!flg2) PetscFunctionReturn(0); 2566 2567 if (nz == SKIP_ALLOCATION) { 2568 skipallocation = PETSC_TRUE; 2569 nz = 0; 2570 } 2571 2572 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 2573 if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz); 2574 if (nnz) { 2575 for (i=0; i<B->m; i++) { 2576 if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]); 2577 if (nnz[i] > B->n) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %d value %d rowlength %d",i,nnz[i],B->n); 2578 } 2579 } 2580 2581 B->preallocated = PETSC_TRUE; 2582 b = (Mat_SeqAIJ*)B->data; 2583 2584 ierr = PetscMalloc((B->m+1)*sizeof(int),&b->imax);CHKERRQ(ierr); 2585 if (!nnz) { 2586 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 2587 else if (nz <= 0) nz = 1; 2588 for (i=0; i<B->m; i++) b->imax[i] = nz; 2589 nz = nz*B->m; 2590 } else { 2591 nz = 0; 2592 for (i=0; i<B->m; i++) {b->imax[i] = nnz[i]; nz += nnz[i];} 2593 } 2594 2595 if (!skipallocation) { 2596 /* allocate the matrix space */ 2597 len = nz*(sizeof(int) + sizeof(PetscScalar)) + (B->m+1)*sizeof(int); 2598 ierr = PetscMalloc(len,&b->a);CHKERRQ(ierr); 2599 b->j = (int*)(b->a + nz); 2600 ierr = PetscMemzero(b->j,nz*sizeof(int));CHKERRQ(ierr); 2601 b->i = b->j + nz; 2602 b->singlemalloc = PETSC_TRUE; 2603 b->freedata = PETSC_TRUE; 2604 } else { 2605 b->freedata = PETSC_FALSE; 2606 } 2607 2608 b->i[0] = -b->indexshift; 2609 for (i=1; i<B->m+1; i++) { 2610 b->i[i] = b->i[i-1] + b->imax[i-1]; 2611 } 2612 2613 /* b->ilen will count nonzeros in each row so far. */ 2614 ierr = PetscMalloc((B->m+1)*sizeof(int),&b->ilen);CHKERRQ(ierr); 2615 PetscLogObjectMemory(B,len+2*(B->m+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqAIJ)); 2616 for (i=0; i<B->m; i++) { b->ilen[i] = 0;} 2617 2618 b->nz = 0; 2619 b->maxnz = nz; 2620 B->info.nz_unneeded = (double)b->maxnz; 2621 PetscFunctionReturn(0); 2622 } 2623 2624 EXTERN_C_BEGIN 2625 #undef __FUNCT__ 2626 #define __FUNCT__ "MatCreate_SeqAIJ" 2627 int MatCreate_SeqAIJ(Mat B) 2628 { 2629 Mat_SeqAIJ *b; 2630 int ierr,size; 2631 PetscTruth flg; 2632 2633 PetscFunctionBegin; 2634 ierr = MPI_Comm_size(B->comm,&size);CHKERRQ(ierr); 2635 if (size > 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1"); 2636 2637 B->m = B->M = PetscMax(B->m,B->M); 2638 B->n = B->N = PetscMax(B->n,B->N); 2639 2640 ierr = PetscNew(Mat_SeqAIJ,&b);CHKERRQ(ierr); 2641 B->data = (void*)b; 2642 ierr = PetscMemzero(b,sizeof(Mat_SeqAIJ));CHKERRQ(ierr); 2643 ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 2644 B->factor = 0; 2645 B->lupivotthreshold = 1.0; 2646 B->mapping = 0; 2647 ierr = PetscOptionsGetReal(PETSC_NULL,"-mat_lu_pivotthreshold",&B->lupivotthreshold,PETSC_NULL);CHKERRQ(ierr); 2648 ierr = PetscOptionsHasName(PETSC_NULL,"-pc_ilu_preserve_row_sums",&b->ilu_preserve_row_sums);CHKERRQ(ierr); 2649 b->row = 0; 2650 b->col = 0; 2651 b->icol = 0; 2652 b->indexshift = 0; 2653 b->reallocs = 0; 2654 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_oneindex",&flg);CHKERRQ(ierr); 2655 if (flg) b->indexshift = -1; 2656 2657 ierr = PetscMapCreateMPI(B->comm,B->m,B->m,&B->rmap);CHKERRQ(ierr); 2658 ierr = PetscMapCreateMPI(B->comm,B->n,B->n,&B->cmap);CHKERRQ(ierr); 2659 2660 b->sorted = PETSC_FALSE; 2661 b->ignorezeroentries = PETSC_FALSE; 2662 b->roworiented = PETSC_TRUE; 2663 b->nonew = 0; 2664 b->diag = 0; 2665 b->solve_work = 0; 2666 B->spptr = 0; 2667 b->inode.use = PETSC_TRUE; 2668 b->inode.node_count = 0; 2669 b->inode.size = 0; 2670 b->inode.limit = 5; 2671 b->inode.max_limit = 5; 2672 b->saved_values = 0; 2673 b->idiag = 0; 2674 b->ssor = 0; 2675 b->keepzeroedrows = PETSC_FALSE; 2676 2677 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 2678 2679 #if defined(PETSC_HAVE_SUPERLU) 2680 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_superlu",&flg);CHKERRQ(ierr); 2681 if (flg) { ierr = MatUseSuperLU_SeqAIJ(B);CHKERRQ(ierr); } 2682 #endif 2683 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_essl",&flg);CHKERRQ(ierr); 2684 if (flg) { ierr = MatUseEssl_SeqAIJ(B);CHKERRQ(ierr); } 2685 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_lusol",&flg);CHKERRQ(ierr); 2686 if (flg) { ierr = MatUseLUSOL_SeqAIJ(B);CHKERRQ(ierr); } 2687 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_matlab",&flg);CHKERRQ(ierr); 2688 if (flg) {ierr = MatUseMatlab_SeqAIJ(B);CHKERRQ(ierr);} 2689 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_dxml",&flg);CHKERRQ(ierr); 2690 if (flg) { 2691 if (!b->indexshift) SETERRQ(PETSC_ERR_LIB,"need -mat_aij_oneindex with -mat_aij_dxml"); 2692 ierr = MatUseDXML_SeqAIJ(B);CHKERRQ(ierr); 2693 } 2694 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C", 2695 "MatSeqAIJSetColumnIndices_SeqAIJ", 2696 MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr); 2697 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C", 2698 "MatStoreValues_SeqAIJ", 2699 MatStoreValues_SeqAIJ);CHKERRQ(ierr); 2700 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C", 2701 "MatRetrieveValues_SeqAIJ", 2702 MatRetrieveValues_SeqAIJ);CHKERRQ(ierr); 2703 #if defined(PETSC_HAVE_MATLAB_ENGINE) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE) 2704 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEnginePut_C","MatMatlabEnginePut_SeqAIJ",MatMatlabEnginePut_SeqAIJ);CHKERRQ(ierr); 2705 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEngineGet_C","MatMatlabEngineGet_SeqAIJ",MatMatlabEngineGet_SeqAIJ);CHKERRQ(ierr); 2706 #endif 2707 PetscFunctionReturn(0); 2708 } 2709 EXTERN_C_END 2710 2711 #undef __FUNCT__ 2712 #define __FUNCT__ "MatDuplicate_SeqAIJ" 2713 int MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B) 2714 { 2715 Mat C; 2716 Mat_SeqAIJ *c,*a = (Mat_SeqAIJ*)A->data; 2717 int i,len,m = A->m,shift = a->indexshift,ierr; 2718 2719 PetscFunctionBegin; 2720 *B = 0; 2721 ierr = MatCreate(A->comm,A->m,A->n,A->m,A->n,&C);CHKERRQ(ierr); 2722 ierr = MatSetType(C,MATSEQAIJ);CHKERRQ(ierr); 2723 c = (Mat_SeqAIJ*)C->data; 2724 2725 C->factor = A->factor; 2726 c->row = 0; 2727 c->col = 0; 2728 c->icol = 0; 2729 c->indexshift = shift; 2730 c->keepzeroedrows = a->keepzeroedrows; 2731 C->assembled = PETSC_TRUE; 2732 2733 C->M = A->m; 2734 C->N = A->n; 2735 2736 ierr = PetscMalloc((m+1)*sizeof(int),&c->imax);CHKERRQ(ierr); 2737 ierr = PetscMalloc((m+1)*sizeof(int),&c->ilen);CHKERRQ(ierr); 2738 for (i=0; i<m; i++) { 2739 c->imax[i] = a->imax[i]; 2740 c->ilen[i] = a->ilen[i]; 2741 } 2742 2743 /* allocate the matrix space */ 2744 c->singlemalloc = PETSC_TRUE; 2745 len = (m+1)*sizeof(int)+(a->i[m])*(sizeof(PetscScalar)+sizeof(int)); 2746 ierr = PetscMalloc(len,&c->a);CHKERRQ(ierr); 2747 c->j = (int*)(c->a + a->i[m] + shift); 2748 c->i = c->j + a->i[m] + shift; 2749 ierr = PetscMemcpy(c->i,a->i,(m+1)*sizeof(int));CHKERRQ(ierr); 2750 if (m > 0) { 2751 ierr = PetscMemcpy(c->j,a->j,(a->i[m]+shift)*sizeof(int));CHKERRQ(ierr); 2752 if (cpvalues == MAT_COPY_VALUES) { 2753 ierr = PetscMemcpy(c->a,a->a,(a->i[m]+shift)*sizeof(PetscScalar));CHKERRQ(ierr); 2754 } else { 2755 ierr = PetscMemzero(c->a,(a->i[m]+shift)*sizeof(PetscScalar));CHKERRQ(ierr); 2756 } 2757 } 2758 2759 PetscLogObjectMemory(C,len+2*(m+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqAIJ)); 2760 c->sorted = a->sorted; 2761 c->roworiented = a->roworiented; 2762 c->nonew = a->nonew; 2763 c->ilu_preserve_row_sums = a->ilu_preserve_row_sums; 2764 c->saved_values = 0; 2765 c->idiag = 0; 2766 c->ssor = 0; 2767 c->ignorezeroentries = a->ignorezeroentries; 2768 c->freedata = PETSC_TRUE; 2769 2770 if (a->diag) { 2771 ierr = PetscMalloc((m+1)*sizeof(int),&c->diag);CHKERRQ(ierr); 2772 PetscLogObjectMemory(C,(m+1)*sizeof(int)); 2773 for (i=0; i<m; i++) { 2774 c->diag[i] = a->diag[i]; 2775 } 2776 } else c->diag = 0; 2777 c->inode.use = a->inode.use; 2778 c->inode.limit = a->inode.limit; 2779 c->inode.max_limit = a->inode.max_limit; 2780 if (a->inode.size){ 2781 ierr = PetscMalloc((m+1)*sizeof(int),&c->inode.size);CHKERRQ(ierr); 2782 c->inode.node_count = a->inode.node_count; 2783 ierr = PetscMemcpy(c->inode.size,a->inode.size,(m+1)*sizeof(int));CHKERRQ(ierr); 2784 } else { 2785 c->inode.size = 0; 2786 c->inode.node_count = 0; 2787 } 2788 c->nz = a->nz; 2789 c->maxnz = a->maxnz; 2790 c->solve_work = 0; 2791 C->spptr = 0; /* Dangerous -I'm throwing away a->spptr */ 2792 C->preallocated = PETSC_TRUE; 2793 2794 *B = C; 2795 ierr = PetscFListDuplicate(A->qlist,&C->qlist);CHKERRQ(ierr); 2796 PetscFunctionReturn(0); 2797 } 2798 2799 EXTERN_C_BEGIN 2800 #undef __FUNCT__ 2801 #define __FUNCT__ "MatLoad_SeqAIJ" 2802 int MatLoad_SeqAIJ(PetscViewer viewer,MatType type,Mat *A) 2803 { 2804 Mat_SeqAIJ *a; 2805 Mat B; 2806 int i,nz,ierr,fd,header[4],size,*rowlengths = 0,M,N,shift; 2807 MPI_Comm comm; 2808 2809 PetscFunctionBegin; 2810 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 2811 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 2812 if (size > 1) SETERRQ(PETSC_ERR_ARG_SIZ,"view must have one processor"); 2813 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 2814 ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr); 2815 if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file"); 2816 M = header[1]; N = header[2]; nz = header[3]; 2817 2818 if (nz < 0) { 2819 SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ"); 2820 } 2821 2822 /* read in row lengths */ 2823 ierr = PetscMalloc(M*sizeof(int),&rowlengths);CHKERRQ(ierr); 2824 ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr); 2825 2826 /* create our matrix */ 2827 ierr = MatCreateSeqAIJ(comm,M,N,0,rowlengths,A);CHKERRQ(ierr); 2828 B = *A; 2829 a = (Mat_SeqAIJ*)B->data; 2830 shift = a->indexshift; 2831 2832 /* read in column indices and adjust for Fortran indexing*/ 2833 ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT);CHKERRQ(ierr); 2834 if (shift) { 2835 for (i=0; i<nz; i++) { 2836 a->j[i] += 1; 2837 } 2838 } 2839 2840 /* read in nonzero values */ 2841 ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);CHKERRQ(ierr); 2842 2843 /* set matrix "i" values */ 2844 a->i[0] = -shift; 2845 for (i=1; i<= M; i++) { 2846 a->i[i] = a->i[i-1] + rowlengths[i-1]; 2847 a->ilen[i-1] = rowlengths[i-1]; 2848 } 2849 ierr = PetscFree(rowlengths);CHKERRQ(ierr); 2850 2851 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2852 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2853 PetscFunctionReturn(0); 2854 } 2855 EXTERN_C_END 2856 2857 #undef __FUNCT__ 2858 #define __FUNCT__ "MatEqual_SeqAIJ" 2859 int MatEqual_SeqAIJ(Mat A,Mat B,PetscTruth* flg) 2860 { 2861 Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data; 2862 int ierr; 2863 PetscTruth flag; 2864 2865 PetscFunctionBegin; 2866 ierr = PetscTypeCompare((PetscObject)B,MATSEQAIJ,&flag);CHKERRQ(ierr); 2867 if (!flag) SETERRQ(PETSC_ERR_ARG_INCOMP,"Matrices must be same type"); 2868 2869 /* If the matrix dimensions are not equal,or no of nonzeros or shift */ 2870 if ((A->m != B->m) || (A->n != B->n) ||(a->nz != b->nz)|| (a->indexshift != b->indexshift)) { 2871 *flg = PETSC_FALSE; 2872 PetscFunctionReturn(0); 2873 } 2874 2875 /* if the a->i are the same */ 2876 ierr = PetscMemcmp(a->i,b->i,(A->m+1)*sizeof(int),flg);CHKERRQ(ierr); 2877 if (*flg == PETSC_FALSE) PetscFunctionReturn(0); 2878 2879 /* if a->j are the same */ 2880 ierr = PetscMemcmp(a->j,b->j,(a->nz)*sizeof(int),flg);CHKERRQ(ierr); 2881 if (*flg == PETSC_FALSE) PetscFunctionReturn(0); 2882 2883 /* if a->a are the same */ 2884 ierr = PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);CHKERRQ(ierr); 2885 2886 PetscFunctionReturn(0); 2887 2888 } 2889 2890 #undef __FUNCT__ 2891 #define __FUNCT__ "MatCreateSeqAIJWithArrays" 2892 /*@C 2893 MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format) 2894 provided by the user. 2895 2896 Coolective on MPI_Comm 2897 2898 Input Parameters: 2899 + comm - must be an MPI communicator of size 1 2900 . m - number of rows 2901 . n - number of columns 2902 . i - row indices 2903 . j - column indices 2904 - a - matrix values 2905 2906 Output Parameter: 2907 . mat - the matrix 2908 2909 Level: intermediate 2910 2911 Notes: 2912 The i, j, and a arrays are not copied by this routine, the user must free these arrays 2913 once the matrix is destroyed 2914 2915 You cannot set new nonzero locations into this matrix, that will generate an error. 2916 2917 The i and j indices can be either 0- or 1 based 2918 2919 .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ() 2920 2921 @*/ 2922 int MatCreateSeqAIJWithArrays(MPI_Comm comm,int m,int n,int* i,int*j,PetscScalar *a,Mat *mat) 2923 { 2924 int ierr,ii; 2925 Mat_SeqAIJ *aij; 2926 2927 PetscFunctionBegin; 2928 ierr = MatCreateSeqAIJ(comm,m,n,SKIP_ALLOCATION,0,mat);CHKERRQ(ierr); 2929 aij = (Mat_SeqAIJ*)(*mat)->data; 2930 2931 if (i[0] == 1) { 2932 aij->indexshift = -1; 2933 } else if (i[0]) { 2934 SETERRQ(1,"i (row indices) do not start with 0 or 1"); 2935 } 2936 aij->i = i; 2937 aij->j = j; 2938 aij->a = a; 2939 aij->singlemalloc = PETSC_FALSE; 2940 aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 2941 aij->freedata = PETSC_FALSE; 2942 2943 for (ii=0; ii<m; ii++) { 2944 aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii]; 2945 #if defined(PETSC_USE_BOPT_g) 2946 if (i[ii+1] - i[ii] < 0) SETERRQ2(1,"Negative row length in i (row indices) row = %d length = %d",ii,i[ii+1] - i[ii]); 2947 #endif 2948 } 2949 #if defined(PETSC_USE_BOPT_g) 2950 for (ii=0; ii<aij->i[m]; ii++) { 2951 if (j[ii] < -aij->indexshift) SETERRQ2(1,"Negative column index at location = %d index = %d",ii,j[ii]); 2952 if (j[ii] > n - 1 -aij->indexshift) SETERRQ2(1,"Column index to large at location = %d index = %d",ii,j[ii]); 2953 } 2954 #endif 2955 2956 /* changes indices to start at 0 */ 2957 if (i[0]) { 2958 aij->indexshift = 0; 2959 for (ii=0; ii<m; ii++) { 2960 i[ii]--; 2961 } 2962 for (ii=0; ii<i[m]; ii++) { 2963 j[ii]--; 2964 } 2965 } 2966 2967 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2968 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2969 PetscFunctionReturn(0); 2970 } 2971 2972 #undef __FUNCT__ 2973 #define __FUNCT__ "MatSetColoring_SeqAIJ" 2974 int MatSetColoring_SeqAIJ(Mat A,ISColoring coloring) 2975 { 2976 int ierr; 2977 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2978 2979 PetscFunctionBegin; 2980 ierr = ISColoringReference(coloring);CHKERRQ(ierr); 2981 a->coloring = coloring; 2982 PetscFunctionReturn(0); 2983 } 2984 2985 #if defined(PETSC_HAVE_ADIC) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE) 2986 EXTERN_C_BEGIN 2987 #include "adic/ad_utils.h" 2988 EXTERN_C_END 2989 2990 #undef __FUNCT__ 2991 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ" 2992 int MatSetValuesAdic_SeqAIJ(Mat A,void *advalues) 2993 { 2994 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2995 int m = A->m,*ii = a->i,*jj = a->j,nz,i,*color,j,nlen; 2996 PetscScalar *v = a->a,*values; 2997 char *cadvalues = (char *)advalues; 2998 2999 PetscFunctionBegin; 3000 if (!a->coloring) SETERRQ(1,"Coloring not set for matrix"); 3001 nlen = PetscADGetDerivTypeSize(); 3002 color = a->coloring->colors; 3003 /* loop over rows */ 3004 for (i=0; i<m; i++) { 3005 nz = ii[i+1] - ii[i]; 3006 /* loop over columns putting computed value into matrix */ 3007 values = PetscADGetGradArray(cadvalues); 3008 for (j=0; j<nz; j++) { 3009 *v++ = values[color[*jj++]]; 3010 } 3011 cadvalues += nlen; /* jump to next row of derivatives */ 3012 } 3013 PetscFunctionReturn(0); 3014 } 3015 3016 #else 3017 3018 #undef __FUNCT__ 3019 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ" 3020 int MatSetValuesAdic_SeqAIJ(Mat A,void *advalues) 3021 { 3022 PetscFunctionBegin; 3023 SETERRQ(1,"PETSc installed without ADIC"); 3024 } 3025 3026 #endif 3027 3028 #undef __FUNCT__ 3029 #define __FUNCT__ "MatSetValuesAdifor_SeqAIJ" 3030 int MatSetValuesAdifor_SeqAIJ(Mat A,int nl,void *advalues) 3031 { 3032 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3033 int m = A->m,*ii = a->i,*jj = a->j,nz,i,*color,j; 3034 PetscScalar *v = a->a,*values = (PetscScalar *)advalues; 3035 3036 PetscFunctionBegin; 3037 if (!a->coloring) SETERRQ(1,"Coloring not set for matrix"); 3038 color = a->coloring->colors; 3039 /* loop over rows */ 3040 for (i=0; i<m; i++) { 3041 nz = ii[i+1] - ii[i]; 3042 /* loop over columns putting computed value into matrix */ 3043 for (j=0; j<nz; j++) { 3044 *v++ = values[color[*jj++]]; 3045 } 3046 values += nl; /* jump to next row of derivatives */ 3047 } 3048 PetscFunctionReturn(0); 3049 } 3050 3051