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