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