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 PetscBLASInt bnz = (PetscBLASInt)a->nz,one = 1; 1713 1714 PetscFunctionBegin; 1715 BLscal_(&bnz,(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 i; 2076 Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data,*y = (Mat_SeqAIJ *)Y->data; 2077 PetscBLASInt one=1,bnz = (PetscBLASInt)x->nz; 2078 2079 PetscFunctionBegin; 2080 if (str == SAME_NONZERO_PATTERN) { 2081 BLaxpy_(&bnz,(PetscScalar*)a,x->a,&one,y->a,&one); 2082 } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 2083 if (y->xtoy && y->XtoY != X) { 2084 ierr = PetscFree(y->xtoy);CHKERRQ(ierr); 2085 ierr = MatDestroy(y->XtoY);CHKERRQ(ierr); 2086 } 2087 if (!y->xtoy) { /* get xtoy */ 2088 ierr = MatAXPYGetxtoy_Private(X->m,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);CHKERRQ(ierr); 2089 y->XtoY = X; 2090 } 2091 for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += (*a)*(x->a[i]); 2092 PetscLogInfo(0,"MatAXPY_SeqAIJ: ratio of nnz(X)/nnz(Y): %d/%d = %g\n",x->nz,y->nz,(PetscReal)(x->nz)/y->nz); 2093 } else { 2094 ierr = MatAXPY_Basic(a,X,Y,str);CHKERRQ(ierr); 2095 } 2096 PetscFunctionReturn(0); 2097 } 2098 2099 /* -------------------------------------------------------------------*/ 2100 static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ, 2101 MatGetRow_SeqAIJ, 2102 MatRestoreRow_SeqAIJ, 2103 MatMult_SeqAIJ, 2104 /* 4*/ MatMultAdd_SeqAIJ, 2105 MatMultTranspose_SeqAIJ, 2106 MatMultTransposeAdd_SeqAIJ, 2107 MatSolve_SeqAIJ, 2108 MatSolveAdd_SeqAIJ, 2109 MatSolveTranspose_SeqAIJ, 2110 /*10*/ MatSolveTransposeAdd_SeqAIJ, 2111 MatLUFactor_SeqAIJ, 2112 0, 2113 MatRelax_SeqAIJ, 2114 MatTranspose_SeqAIJ, 2115 /*15*/ MatGetInfo_SeqAIJ, 2116 MatEqual_SeqAIJ, 2117 MatGetDiagonal_SeqAIJ, 2118 MatDiagonalScale_SeqAIJ, 2119 MatNorm_SeqAIJ, 2120 /*20*/ 0, 2121 MatAssemblyEnd_SeqAIJ, 2122 MatCompress_SeqAIJ, 2123 MatSetOption_SeqAIJ, 2124 MatZeroEntries_SeqAIJ, 2125 /*25*/ MatZeroRows_SeqAIJ, 2126 MatLUFactorSymbolic_SeqAIJ, 2127 MatLUFactorNumeric_SeqAIJ, 2128 MatCholeskyFactorSymbolic_SeqAIJ, 2129 MatCholeskyFactorNumeric_SeqAIJ, 2130 /*30*/ MatSetUpPreallocation_SeqAIJ, 2131 MatILUFactorSymbolic_SeqAIJ, 2132 MatICCFactorSymbolic_SeqAIJ, 2133 MatGetArray_SeqAIJ, 2134 MatRestoreArray_SeqAIJ, 2135 /*35*/ MatDuplicate_SeqAIJ, 2136 0, 2137 0, 2138 MatILUFactor_SeqAIJ, 2139 0, 2140 /*40*/ MatAXPY_SeqAIJ, 2141 MatGetSubMatrices_SeqAIJ, 2142 MatIncreaseOverlap_SeqAIJ, 2143 MatGetValues_SeqAIJ, 2144 MatCopy_SeqAIJ, 2145 /*45*/ MatPrintHelp_SeqAIJ, 2146 MatScale_SeqAIJ, 2147 0, 2148 0, 2149 MatILUDTFactor_SeqAIJ, 2150 /*50*/ MatGetBlockSize_SeqAIJ, 2151 MatGetRowIJ_SeqAIJ, 2152 MatRestoreRowIJ_SeqAIJ, 2153 MatGetColumnIJ_SeqAIJ, 2154 MatRestoreColumnIJ_SeqAIJ, 2155 /*55*/ MatFDColoringCreate_SeqAIJ, 2156 0, 2157 0, 2158 MatPermute_SeqAIJ, 2159 0, 2160 /*60*/ 0, 2161 MatDestroy_SeqAIJ, 2162 MatView_SeqAIJ, 2163 MatGetPetscMaps_Petsc, 2164 0, 2165 /*65*/ 0, 2166 0, 2167 0, 2168 0, 2169 0, 2170 /*70*/ 0, 2171 0, 2172 MatSetColoring_SeqAIJ, 2173 MatSetValuesAdic_SeqAIJ, 2174 MatSetValuesAdifor_SeqAIJ, 2175 /*75*/ MatFDColoringApply_SeqAIJ, 2176 0, 2177 0, 2178 0, 2179 0, 2180 /*80*/ 0, 2181 0, 2182 0, 2183 0, 2184 /*84*/ MatLoad_SeqAIJ, 2185 MatIsSymmetric_SeqAIJ, 2186 0, 2187 0, 2188 0, 2189 /*89*/ 0, 2190 MatMatMult_SeqAIJ_SeqAIJ, 2191 MatMatMultSymbolic_SeqAIJ_SeqAIJ, 2192 MatMatMultNumeric_SeqAIJ_SeqAIJ, 2193 MatPtAP_SeqAIJ_SeqAIJ, 2194 /*94*/ MatPtAPSymbolic_SeqAIJ_SeqAIJ, 2195 MatPtAPNumeric_SeqAIJ_SeqAIJ, 2196 }; 2197 2198 EXTERN_C_BEGIN 2199 #undef __FUNCT__ 2200 #define __FUNCT__ "MatSeqAIJSetColumnIndices_SeqAIJ" 2201 PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,int *indices) 2202 { 2203 Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2204 int i,nz,n; 2205 2206 PetscFunctionBegin; 2207 2208 nz = aij->maxnz; 2209 n = mat->n; 2210 for (i=0; i<nz; i++) { 2211 aij->j[i] = indices[i]; 2212 } 2213 aij->nz = nz; 2214 for (i=0; i<n; i++) { 2215 aij->ilen[i] = aij->imax[i]; 2216 } 2217 2218 PetscFunctionReturn(0); 2219 } 2220 EXTERN_C_END 2221 2222 #undef __FUNCT__ 2223 #define __FUNCT__ "MatSeqAIJSetColumnIndices" 2224 /*@ 2225 MatSeqAIJSetColumnIndices - Set the column indices for all the rows 2226 in the matrix. 2227 2228 Input Parameters: 2229 + mat - the SeqAIJ matrix 2230 - indices - the column indices 2231 2232 Level: advanced 2233 2234 Notes: 2235 This can be called if you have precomputed the nonzero structure of the 2236 matrix and want to provide it to the matrix object to improve the performance 2237 of the MatSetValues() operation. 2238 2239 You MUST have set the correct numbers of nonzeros per row in the call to 2240 MatCreateSeqAIJ(). 2241 2242 MUST be called before any calls to MatSetValues(); 2243 2244 The indices should start with zero, not one. 2245 2246 @*/ 2247 PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat,int *indices) 2248 { 2249 PetscErrorCode ierr,(*f)(Mat,int *); 2250 2251 PetscFunctionBegin; 2252 PetscValidHeaderSpecific(mat,MAT_COOKIE,1); 2253 PetscValidPointer(indices,2); 2254 ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqAIJSetColumnIndices_C",(void (**)(void))&f);CHKERRQ(ierr); 2255 if (f) { 2256 ierr = (*f)(mat,indices);CHKERRQ(ierr); 2257 } else { 2258 SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to set column indices"); 2259 } 2260 PetscFunctionReturn(0); 2261 } 2262 2263 /* ----------------------------------------------------------------------------------------*/ 2264 2265 EXTERN_C_BEGIN 2266 #undef __FUNCT__ 2267 #define __FUNCT__ "MatStoreValues_SeqAIJ" 2268 PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) 2269 { 2270 Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2271 PetscErrorCode ierr; 2272 size_t nz = aij->i[mat->m]; 2273 2274 PetscFunctionBegin; 2275 if (aij->nonew != 1) { 2276 SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first"); 2277 } 2278 2279 /* allocate space for values if not already there */ 2280 if (!aij->saved_values) { 2281 ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr); 2282 } 2283 2284 /* copy values over */ 2285 ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr); 2286 PetscFunctionReturn(0); 2287 } 2288 EXTERN_C_END 2289 2290 #undef __FUNCT__ 2291 #define __FUNCT__ "MatStoreValues" 2292 /*@ 2293 MatStoreValues - Stashes a copy of the matrix values; this allows, for 2294 example, reuse of the linear part of a Jacobian, while recomputing the 2295 nonlinear portion. 2296 2297 Collect on Mat 2298 2299 Input Parameters: 2300 . mat - the matrix (currently on AIJ matrices support this option) 2301 2302 Level: advanced 2303 2304 Common Usage, with SNESSolve(): 2305 $ Create Jacobian matrix 2306 $ Set linear terms into matrix 2307 $ Apply boundary conditions to matrix, at this time matrix must have 2308 $ final nonzero structure (i.e. setting the nonlinear terms and applying 2309 $ boundary conditions again will not change the nonzero structure 2310 $ ierr = MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS); 2311 $ ierr = MatStoreValues(mat); 2312 $ Call SNESSetJacobian() with matrix 2313 $ In your Jacobian routine 2314 $ ierr = MatRetrieveValues(mat); 2315 $ Set nonlinear terms in matrix 2316 2317 Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself: 2318 $ // build linear portion of Jacobian 2319 $ ierr = MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS); 2320 $ ierr = MatStoreValues(mat); 2321 $ loop over nonlinear iterations 2322 $ ierr = MatRetrieveValues(mat); 2323 $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian 2324 $ // call MatAssemblyBegin/End() on matrix 2325 $ Solve linear system with Jacobian 2326 $ endloop 2327 2328 Notes: 2329 Matrix must already be assemblied before calling this routine 2330 Must set the matrix option MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS); before 2331 calling this routine. 2332 2333 .seealso: MatRetrieveValues() 2334 2335 @*/ 2336 PetscErrorCode MatStoreValues(Mat mat) 2337 { 2338 PetscErrorCode ierr,(*f)(Mat); 2339 2340 PetscFunctionBegin; 2341 PetscValidHeaderSpecific(mat,MAT_COOKIE,1); 2342 if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 2343 if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2344 2345 ierr = PetscObjectQueryFunction((PetscObject)mat,"MatStoreValues_C",(void (**)(void))&f);CHKERRQ(ierr); 2346 if (f) { 2347 ierr = (*f)(mat);CHKERRQ(ierr); 2348 } else { 2349 SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to store values"); 2350 } 2351 PetscFunctionReturn(0); 2352 } 2353 2354 EXTERN_C_BEGIN 2355 #undef __FUNCT__ 2356 #define __FUNCT__ "MatRetrieveValues_SeqAIJ" 2357 PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat) 2358 { 2359 Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2360 PetscErrorCode ierr; 2361 int nz = aij->i[mat->m]; 2362 2363 PetscFunctionBegin; 2364 if (aij->nonew != 1) { 2365 SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first"); 2366 } 2367 if (!aij->saved_values) { 2368 SETERRQ(PETSC_ERR_ORDER,"Must call MatStoreValues(A);first"); 2369 } 2370 /* copy values over */ 2371 ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr); 2372 PetscFunctionReturn(0); 2373 } 2374 EXTERN_C_END 2375 2376 #undef __FUNCT__ 2377 #define __FUNCT__ "MatRetrieveValues" 2378 /*@ 2379 MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 2380 example, reuse of the linear part of a Jacobian, while recomputing the 2381 nonlinear portion. 2382 2383 Collect on Mat 2384 2385 Input Parameters: 2386 . mat - the matrix (currently on AIJ matrices support this option) 2387 2388 Level: advanced 2389 2390 .seealso: MatStoreValues() 2391 2392 @*/ 2393 PetscErrorCode MatRetrieveValues(Mat mat) 2394 { 2395 PetscErrorCode ierr,(*f)(Mat); 2396 2397 PetscFunctionBegin; 2398 PetscValidHeaderSpecific(mat,MAT_COOKIE,1); 2399 if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 2400 if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2401 2402 ierr = PetscObjectQueryFunction((PetscObject)mat,"MatRetrieveValues_C",(void (**)(void))&f);CHKERRQ(ierr); 2403 if (f) { 2404 ierr = (*f)(mat);CHKERRQ(ierr); 2405 } else { 2406 SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to retrieve values"); 2407 } 2408 PetscFunctionReturn(0); 2409 } 2410 2411 2412 /* --------------------------------------------------------------------------------*/ 2413 #undef __FUNCT__ 2414 #define __FUNCT__ "MatCreateSeqAIJ" 2415 /*@C 2416 MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format 2417 (the default parallel PETSc format). For good matrix assembly performance 2418 the user should preallocate the matrix storage by setting the parameter nz 2419 (or the array nnz). By setting these parameters accurately, performance 2420 during matrix assembly can be increased by more than a factor of 50. 2421 2422 Collective on MPI_Comm 2423 2424 Input Parameters: 2425 + comm - MPI communicator, set to PETSC_COMM_SELF 2426 . m - number of rows 2427 . n - number of columns 2428 . nz - number of nonzeros per row (same for all rows) 2429 - nnz - array containing the number of nonzeros in the various rows 2430 (possibly different for each row) or PETSC_NULL 2431 2432 Output Parameter: 2433 . A - the matrix 2434 2435 Notes: 2436 The AIJ format (also called the Yale sparse matrix format or 2437 compressed row storage), is fully compatible with standard Fortran 77 2438 storage. That is, the stored row and column indices can begin at 2439 either one (as in Fortran) or zero. See the users' manual for details. 2440 2441 Specify the preallocated storage with either nz or nnz (not both). 2442 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 2443 allocation. For large problems you MUST preallocate memory or you 2444 will get TERRIBLE performance, see the users' manual chapter on matrices. 2445 2446 By default, this format uses inodes (identical nodes) when possible, to 2447 improve numerical efficiency of matrix-vector products and solves. We 2448 search for consecutive rows with the same nonzero structure, thereby 2449 reusing matrix information to achieve increased efficiency. 2450 2451 Options Database Keys: 2452 + -mat_aij_no_inode - Do not use inodes 2453 . -mat_aij_inode_limit <limit> - Sets inode limit (max limit=5) 2454 - -mat_aij_oneindex - Internally use indexing starting at 1 2455 rather than 0. Note that when calling MatSetValues(), 2456 the user still MUST index entries starting at 0! 2457 2458 Level: intermediate 2459 2460 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays() 2461 2462 @*/ 2463 PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm,int m,int n,int nz,const int nnz[],Mat *A) 2464 { 2465 PetscErrorCode ierr; 2466 2467 PetscFunctionBegin; 2468 ierr = MatCreate(comm,m,n,m,n,A);CHKERRQ(ierr); 2469 ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr); 2470 ierr = MatSeqAIJSetPreallocation(*A,nz,nnz);CHKERRQ(ierr); 2471 PetscFunctionReturn(0); 2472 } 2473 2474 #define SKIP_ALLOCATION -4 2475 2476 #undef __FUNCT__ 2477 #define __FUNCT__ "MatSeqAIJSetPreallocation" 2478 /*@C 2479 MatSeqAIJSetPreallocation - For good matrix assembly performance 2480 the user should preallocate the matrix storage by setting the parameter nz 2481 (or the array nnz). By setting these parameters accurately, performance 2482 during matrix assembly can be increased by more than a factor of 50. 2483 2484 Collective on MPI_Comm 2485 2486 Input Parameters: 2487 + comm - MPI communicator, set to PETSC_COMM_SELF 2488 . m - number of rows 2489 . n - number of columns 2490 . nz - number of nonzeros per row (same for all rows) 2491 - nnz - array containing the number of nonzeros in the various rows 2492 (possibly different for each row) or PETSC_NULL 2493 2494 Output Parameter: 2495 . A - the matrix 2496 2497 Notes: 2498 The AIJ format (also called the Yale sparse matrix format or 2499 compressed row storage), is fully compatible with standard Fortran 77 2500 storage. That is, the stored row and column indices can begin at 2501 either one (as in Fortran) or zero. See the users' manual for details. 2502 2503 Specify the preallocated storage with either nz or nnz (not both). 2504 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 2505 allocation. For large problems you MUST preallocate memory or you 2506 will get TERRIBLE performance, see the users' manual chapter on matrices. 2507 2508 By default, this format uses inodes (identical nodes) when possible, to 2509 improve numerical efficiency of matrix-vector products and solves. We 2510 search for consecutive rows with the same nonzero structure, thereby 2511 reusing matrix information to achieve increased efficiency. 2512 2513 Options Database Keys: 2514 + -mat_aij_no_inode - Do not use inodes 2515 . -mat_aij_inode_limit <limit> - Sets inode limit (max limit=5) 2516 - -mat_aij_oneindex - Internally use indexing starting at 1 2517 rather than 0. Note that when calling MatSetValues(), 2518 the user still MUST index entries starting at 0! 2519 2520 Level: intermediate 2521 2522 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays() 2523 2524 @*/ 2525 PetscErrorCode MatSeqAIJSetPreallocation(Mat B,int nz,const int nnz[]) 2526 { 2527 PetscErrorCode ierr,(*f)(Mat,int,const int[]); 2528 2529 PetscFunctionBegin; 2530 ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr); 2531 if (f) { 2532 ierr = (*f)(B,nz,nnz);CHKERRQ(ierr); 2533 } 2534 PetscFunctionReturn(0); 2535 } 2536 2537 EXTERN_C_BEGIN 2538 #undef __FUNCT__ 2539 #define __FUNCT__ "MatSeqAIJSetPreallocation_SeqAIJ" 2540 PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B,int nz,int *nnz) 2541 { 2542 Mat_SeqAIJ *b; 2543 size_t len = 0; 2544 PetscTruth skipallocation = PETSC_FALSE; 2545 PetscErrorCode ierr; 2546 int i; 2547 2548 PetscFunctionBegin; 2549 2550 if (nz == SKIP_ALLOCATION) { 2551 skipallocation = PETSC_TRUE; 2552 nz = 0; 2553 } 2554 2555 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 2556 if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz); 2557 if (nnz) { 2558 for (i=0; i<B->m; i++) { 2559 if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]); 2560 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); 2561 } 2562 } 2563 2564 B->preallocated = PETSC_TRUE; 2565 b = (Mat_SeqAIJ*)B->data; 2566 2567 ierr = PetscMalloc((B->m+1)*sizeof(int),&b->imax);CHKERRQ(ierr); 2568 if (!nnz) { 2569 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 2570 else if (nz <= 0) nz = 1; 2571 for (i=0; i<B->m; i++) b->imax[i] = nz; 2572 nz = nz*B->m; 2573 } else { 2574 nz = 0; 2575 for (i=0; i<B->m; i++) {b->imax[i] = nnz[i]; nz += nnz[i];} 2576 } 2577 2578 if (!skipallocation) { 2579 /* allocate the matrix space */ 2580 len = ((size_t) nz)*(sizeof(int) + sizeof(PetscScalar)) + (B->m+1)*sizeof(int); 2581 ierr = PetscMalloc(len,&b->a);CHKERRQ(ierr); 2582 b->j = (int*)(b->a + nz); 2583 ierr = PetscMemzero(b->j,nz*sizeof(int));CHKERRQ(ierr); 2584 b->i = b->j + nz; 2585 b->i[0] = 0; 2586 for (i=1; i<B->m+1; i++) { 2587 b->i[i] = b->i[i-1] + b->imax[i-1]; 2588 } 2589 b->singlemalloc = PETSC_TRUE; 2590 b->freedata = PETSC_TRUE; 2591 } else { 2592 b->freedata = PETSC_FALSE; 2593 } 2594 2595 /* b->ilen will count nonzeros in each row so far. */ 2596 ierr = PetscMalloc((B->m+1)*sizeof(int),&b->ilen);CHKERRQ(ierr); 2597 PetscLogObjectMemory(B,len+2*(B->m+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqAIJ)); 2598 for (i=0; i<B->m; i++) { b->ilen[i] = 0;} 2599 2600 b->nz = 0; 2601 b->maxnz = nz; 2602 B->info.nz_unneeded = (double)b->maxnz; 2603 PetscFunctionReturn(0); 2604 } 2605 EXTERN_C_END 2606 2607 /*MC 2608 MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 2609 based on compressed sparse row format. 2610 2611 Options Database Keys: 2612 . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 2613 2614 Level: beginner 2615 2616 .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType 2617 M*/ 2618 2619 EXTERN_C_BEGIN 2620 #undef __FUNCT__ 2621 #define __FUNCT__ "MatCreate_SeqAIJ" 2622 PetscErrorCode MatCreate_SeqAIJ(Mat B) 2623 { 2624 Mat_SeqAIJ *b; 2625 PetscErrorCode ierr; 2626 int size; 2627 2628 PetscFunctionBegin; 2629 ierr = MPI_Comm_size(B->comm,&size);CHKERRQ(ierr); 2630 if (size > 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1"); 2631 2632 B->m = B->M = PetscMax(B->m,B->M); 2633 B->n = B->N = PetscMax(B->n,B->N); 2634 2635 ierr = PetscNew(Mat_SeqAIJ,&b);CHKERRQ(ierr); 2636 B->data = (void*)b; 2637 ierr = PetscMemzero(b,sizeof(Mat_SeqAIJ));CHKERRQ(ierr); 2638 ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 2639 B->factor = 0; 2640 B->lupivotthreshold = 1.0; 2641 B->mapping = 0; 2642 ierr = PetscOptionsGetReal(B->prefix,"-mat_lu_pivotthreshold",&B->lupivotthreshold,PETSC_NULL);CHKERRQ(ierr); 2643 ierr = PetscOptionsHasName(B->prefix,"-pc_ilu_preserve_row_sums",&b->ilu_preserve_row_sums);CHKERRQ(ierr); 2644 b->row = 0; 2645 b->col = 0; 2646 b->icol = 0; 2647 b->reallocs = 0; 2648 2649 ierr = PetscMapCreateMPI(B->comm,B->m,B->m,&B->rmap);CHKERRQ(ierr); 2650 ierr = PetscMapCreateMPI(B->comm,B->n,B->n,&B->cmap);CHKERRQ(ierr); 2651 2652 b->sorted = PETSC_FALSE; 2653 b->ignorezeroentries = PETSC_FALSE; 2654 b->roworiented = PETSC_TRUE; 2655 b->nonew = 0; 2656 b->diag = 0; 2657 b->solve_work = 0; 2658 B->spptr = 0; 2659 b->inode.use = PETSC_TRUE; 2660 b->inode.node_count = 0; 2661 b->inode.size = 0; 2662 b->inode.limit = 5; 2663 b->inode.max_limit = 5; 2664 b->saved_values = 0; 2665 b->idiag = 0; 2666 b->ssor = 0; 2667 b->keepzeroedrows = PETSC_FALSE; 2668 b->xtoy = 0; 2669 b->XtoY = 0; 2670 2671 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 2672 2673 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C", 2674 "MatSeqAIJSetColumnIndices_SeqAIJ", 2675 MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr); 2676 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C", 2677 "MatStoreValues_SeqAIJ", 2678 MatStoreValues_SeqAIJ);CHKERRQ(ierr); 2679 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C", 2680 "MatRetrieveValues_SeqAIJ", 2681 MatRetrieveValues_SeqAIJ);CHKERRQ(ierr); 2682 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqsbaij_C", 2683 "MatConvert_SeqAIJ_SeqSBAIJ", 2684 MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr); 2685 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqbaij_C", 2686 "MatConvert_SeqAIJ_SeqBAIJ", 2687 MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr); 2688 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C", 2689 "MatIsTranspose_SeqAIJ", 2690 MatIsTranspose_SeqAIJ);CHKERRQ(ierr); 2691 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocation_C", 2692 "MatSeqAIJSetPreallocation_SeqAIJ", 2693 MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr); 2694 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatReorderForNonzeroDiagonal_C", 2695 "MatReorderForNonzeroDiagonal_SeqAIJ", 2696 MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr); 2697 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatAdjustForInodes_C", 2698 "MatAdjustForInodes_SeqAIJ", 2699 MatAdjustForInodes_SeqAIJ);CHKERRQ(ierr); 2700 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJGetInodeSizes_C", 2701 "MatSeqAIJGetInodeSizes_SeqAIJ", 2702 MatSeqAIJGetInodeSizes_SeqAIJ);CHKERRQ(ierr); 2703 PetscFunctionReturn(0); 2704 } 2705 EXTERN_C_END 2706 2707 #undef __FUNCT__ 2708 #define __FUNCT__ "MatDuplicate_SeqAIJ" 2709 PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B) 2710 { 2711 Mat C; 2712 Mat_SeqAIJ *c,*a = (Mat_SeqAIJ*)A->data; 2713 PetscErrorCode ierr; 2714 int i,m = A->m; 2715 size_t len; 2716 2717 PetscFunctionBegin; 2718 *B = 0; 2719 ierr = MatCreate(A->comm,A->m,A->n,A->m,A->n,&C);CHKERRQ(ierr); 2720 ierr = MatSetType(C,A->type_name);CHKERRQ(ierr); 2721 ierr = PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 2722 2723 c = (Mat_SeqAIJ*)C->data; 2724 2725 C->factor = A->factor; 2726 c->row = 0; 2727 c->col = 0; 2728 c->icol = 0; 2729 c->keepzeroedrows = a->keepzeroedrows; 2730 C->assembled = PETSC_TRUE; 2731 2732 C->M = A->m; 2733 C->N = A->n; 2734 2735 ierr = PetscMalloc((m+1)*sizeof(int),&c->imax);CHKERRQ(ierr); 2736 ierr = PetscMalloc((m+1)*sizeof(int),&c->ilen);CHKERRQ(ierr); 2737 for (i=0; i<m; i++) { 2738 c->imax[i] = a->imax[i]; 2739 c->ilen[i] = a->ilen[i]; 2740 } 2741 2742 /* allocate the matrix space */ 2743 c->singlemalloc = PETSC_TRUE; 2744 len = ((size_t) (m+1))*sizeof(int)+(a->i[m])*(sizeof(PetscScalar)+sizeof(int)); 2745 ierr = PetscMalloc(len,&c->a);CHKERRQ(ierr); 2746 c->j = (int*)(c->a + a->i[m] ); 2747 c->i = c->j + a->i[m]; 2748 ierr = PetscMemcpy(c->i,a->i,(m+1)*sizeof(int));CHKERRQ(ierr); 2749 if (m > 0) { 2750 ierr = PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(int));CHKERRQ(ierr); 2751 if (cpvalues == MAT_COPY_VALUES) { 2752 ierr = PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr); 2753 } else { 2754 ierr = PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr); 2755 } 2756 } 2757 2758 PetscLogObjectMemory(C,len+2*(m+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqAIJ)); 2759 c->sorted = a->sorted; 2760 c->roworiented = a->roworiented; 2761 c->nonew = a->nonew; 2762 c->ilu_preserve_row_sums = a->ilu_preserve_row_sums; 2763 c->saved_values = 0; 2764 c->idiag = 0; 2765 c->ssor = 0; 2766 c->ignorezeroentries = a->ignorezeroentries; 2767 c->freedata = PETSC_TRUE; 2768 2769 if (a->diag) { 2770 ierr = PetscMalloc((m+1)*sizeof(int),&c->diag);CHKERRQ(ierr); 2771 PetscLogObjectMemory(C,(m+1)*sizeof(int)); 2772 for (i=0; i<m; i++) { 2773 c->diag[i] = a->diag[i]; 2774 } 2775 } else c->diag = 0; 2776 c->inode.use = a->inode.use; 2777 c->inode.limit = a->inode.limit; 2778 c->inode.max_limit = a->inode.max_limit; 2779 if (a->inode.size){ 2780 ierr = PetscMalloc((m+1)*sizeof(int),&c->inode.size);CHKERRQ(ierr); 2781 c->inode.node_count = a->inode.node_count; 2782 ierr = PetscMemcpy(c->inode.size,a->inode.size,(m+1)*sizeof(int));CHKERRQ(ierr); 2783 } else { 2784 c->inode.size = 0; 2785 c->inode.node_count = 0; 2786 } 2787 c->nz = a->nz; 2788 c->maxnz = a->maxnz; 2789 c->solve_work = 0; 2790 C->preallocated = PETSC_TRUE; 2791 2792 *B = C; 2793 ierr = PetscFListDuplicate(A->qlist,&C->qlist);CHKERRQ(ierr); 2794 PetscFunctionReturn(0); 2795 } 2796 2797 #undef __FUNCT__ 2798 #define __FUNCT__ "MatLoad_SeqAIJ" 2799 PetscErrorCode MatLoad_SeqAIJ(PetscViewer viewer,const MatType type,Mat *A) 2800 { 2801 Mat_SeqAIJ *a; 2802 Mat B; 2803 PetscErrorCode ierr; 2804 int i,nz,fd,header[4],size,*rowlengths = 0,M,N; 2805 MPI_Comm comm; 2806 2807 PetscFunctionBegin; 2808 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 2809 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 2810 if (size > 1) SETERRQ(PETSC_ERR_ARG_SIZ,"view must have one processor"); 2811 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 2812 ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr); 2813 if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file"); 2814 M = header[1]; N = header[2]; nz = header[3]; 2815 2816 if (nz < 0) { 2817 SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ"); 2818 } 2819 2820 /* read in row lengths */ 2821 ierr = PetscMalloc(M*sizeof(int),&rowlengths);CHKERRQ(ierr); 2822 ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr); 2823 2824 /* create our matrix */ 2825 ierr = MatCreate(comm,PETSC_DECIDE,PETSC_DECIDE,M,N,&B);CHKERRQ(ierr); 2826 ierr = MatSetType(B,type);CHKERRQ(ierr); 2827 ierr = MatSeqAIJSetPreallocation(B,0,rowlengths);CHKERRQ(ierr); 2828 a = (Mat_SeqAIJ*)B->data; 2829 2830 /* read in column indices and adjust for Fortran indexing*/ 2831 ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT);CHKERRQ(ierr); 2832 2833 /* read in nonzero values */ 2834 ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);CHKERRQ(ierr); 2835 2836 /* set matrix "i" values */ 2837 a->i[0] = 0; 2838 for (i=1; i<= M; i++) { 2839 a->i[i] = a->i[i-1] + rowlengths[i-1]; 2840 a->ilen[i-1] = rowlengths[i-1]; 2841 } 2842 ierr = PetscFree(rowlengths);CHKERRQ(ierr); 2843 2844 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2845 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2846 *A = B; 2847 PetscFunctionReturn(0); 2848 } 2849 2850 #undef __FUNCT__ 2851 #define __FUNCT__ "MatEqual_SeqAIJ" 2852 PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscTruth* flg) 2853 { 2854 Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data; 2855 PetscErrorCode ierr; 2856 2857 PetscFunctionBegin; 2858 /* If the matrix dimensions are not equal,or no of nonzeros */ 2859 if ((A->m != B->m) || (A->n != B->n) ||(a->nz != b->nz)) { 2860 *flg = PETSC_FALSE; 2861 PetscFunctionReturn(0); 2862 } 2863 2864 /* if the a->i are the same */ 2865 ierr = PetscMemcmp(a->i,b->i,(A->m+1)*sizeof(int),flg);CHKERRQ(ierr); 2866 if (*flg == PETSC_FALSE) PetscFunctionReturn(0); 2867 2868 /* if a->j are the same */ 2869 ierr = PetscMemcmp(a->j,b->j,(a->nz)*sizeof(int),flg);CHKERRQ(ierr); 2870 if (*flg == PETSC_FALSE) PetscFunctionReturn(0); 2871 2872 /* if a->a are the same */ 2873 ierr = PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);CHKERRQ(ierr); 2874 2875 PetscFunctionReturn(0); 2876 2877 } 2878 2879 #undef __FUNCT__ 2880 #define __FUNCT__ "MatCreateSeqAIJWithArrays" 2881 /*@C 2882 MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format) 2883 provided by the user. 2884 2885 Coolective on MPI_Comm 2886 2887 Input Parameters: 2888 + comm - must be an MPI communicator of size 1 2889 . m - number of rows 2890 . n - number of columns 2891 . i - row indices 2892 . j - column indices 2893 - a - matrix values 2894 2895 Output Parameter: 2896 . mat - the matrix 2897 2898 Level: intermediate 2899 2900 Notes: 2901 The i, j, and a arrays are not copied by this routine, the user must free these arrays 2902 once the matrix is destroyed 2903 2904 You cannot set new nonzero locations into this matrix, that will generate an error. 2905 2906 The i and j indices are 0 based 2907 2908 .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ() 2909 2910 @*/ 2911 PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm,int m,int n,int* i,int*j,PetscScalar *a,Mat *mat) 2912 { 2913 PetscErrorCode ierr; 2914 int ii; 2915 Mat_SeqAIJ *aij; 2916 2917 PetscFunctionBegin; 2918 ierr = MatCreate(comm,m,n,m,n,mat);CHKERRQ(ierr); 2919 ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr); 2920 ierr = MatSeqAIJSetPreallocation(*mat,SKIP_ALLOCATION,0);CHKERRQ(ierr); 2921 aij = (Mat_SeqAIJ*)(*mat)->data; 2922 2923 if (i[0] != 0) { 2924 SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 2925 } 2926 aij->i = i; 2927 aij->j = j; 2928 aij->a = a; 2929 aij->singlemalloc = PETSC_FALSE; 2930 aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 2931 aij->freedata = PETSC_FALSE; 2932 2933 for (ii=0; ii<m; ii++) { 2934 aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii]; 2935 #if defined(PETSC_USE_BOPT_g) 2936 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]); 2937 #endif 2938 } 2939 #if defined(PETSC_USE_BOPT_g) 2940 for (ii=0; ii<aij->i[m]; ii++) { 2941 if (j[ii] < 0) SETERRQ2(1,"Negative column index at location = %d index = %d",ii,j[ii]); 2942 if (j[ii] > n - 1) SETERRQ2(1,"Column index to large at location = %d index = %d",ii,j[ii]); 2943 } 2944 #endif 2945 2946 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2947 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2948 PetscFunctionReturn(0); 2949 } 2950 2951 #undef __FUNCT__ 2952 #define __FUNCT__ "MatSetColoring_SeqAIJ" 2953 PetscErrorCode MatSetColoring_SeqAIJ(Mat A,ISColoring coloring) 2954 { 2955 PetscErrorCode ierr; 2956 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2957 2958 PetscFunctionBegin; 2959 if (coloring->ctype == IS_COLORING_LOCAL) { 2960 ierr = ISColoringReference(coloring);CHKERRQ(ierr); 2961 a->coloring = coloring; 2962 } else if (coloring->ctype == IS_COLORING_GHOSTED) { 2963 int i,*larray; 2964 ISColoring ocoloring; 2965 ISColoringValue *colors; 2966 2967 /* set coloring for diagonal portion */ 2968 ierr = PetscMalloc((A->n+1)*sizeof(int),&larray);CHKERRQ(ierr); 2969 for (i=0; i<A->n; i++) { 2970 larray[i] = i; 2971 } 2972 ierr = ISGlobalToLocalMappingApply(A->mapping,IS_GTOLM_MASK,A->n,larray,PETSC_NULL,larray);CHKERRQ(ierr); 2973 ierr = PetscMalloc((A->n+1)*sizeof(ISColoringValue),&colors);CHKERRQ(ierr); 2974 for (i=0; i<A->n; i++) { 2975 colors[i] = coloring->colors[larray[i]]; 2976 } 2977 ierr = PetscFree(larray);CHKERRQ(ierr); 2978 ierr = ISColoringCreate(PETSC_COMM_SELF,A->n,colors,&ocoloring);CHKERRQ(ierr); 2979 a->coloring = ocoloring; 2980 } 2981 PetscFunctionReturn(0); 2982 } 2983 2984 #if defined(PETSC_HAVE_ADIC) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE) 2985 EXTERN_C_BEGIN 2986 #include "adic/ad_utils.h" 2987 EXTERN_C_END 2988 2989 #undef __FUNCT__ 2990 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ" 2991 PetscErrorCode MatSetValuesAdic_SeqAIJ(Mat A,void *advalues) 2992 { 2993 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2994 int m = A->m,*ii = a->i,*jj = a->j,nz,i,j,nlen; 2995 PetscScalar *v = a->a,*values = ((PetscScalar*)advalues)+1; 2996 ISColoringValue *color; 2997 2998 PetscFunctionBegin; 2999 if (!a->coloring) SETERRQ(1,"Coloring not set for matrix"); 3000 nlen = PetscADGetDerivTypeSize()/sizeof(PetscScalar); 3001 color = a->coloring->colors; 3002 /* loop over rows */ 3003 for (i=0; i<m; i++) { 3004 nz = ii[i+1] - ii[i]; 3005 /* loop over columns putting computed value into matrix */ 3006 for (j=0; j<nz; j++) { 3007 *v++ = values[color[*jj++]]; 3008 } 3009 values += nlen; /* jump to next row of derivatives */ 3010 } 3011 PetscFunctionReturn(0); 3012 } 3013 3014 #else 3015 3016 #undef __FUNCT__ 3017 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ" 3018 PetscErrorCode MatSetValuesAdic_SeqAIJ(Mat A,void *advalues) 3019 { 3020 PetscFunctionBegin; 3021 SETERRQ(1,"PETSc installed without ADIC"); 3022 } 3023 3024 #endif 3025 3026 #undef __FUNCT__ 3027 #define __FUNCT__ "MatSetValuesAdifor_SeqAIJ" 3028 PetscErrorCode MatSetValuesAdifor_SeqAIJ(Mat A,int nl,void *advalues) 3029 { 3030 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3031 int m = A->m,*ii = a->i,*jj = a->j,nz,i,j; 3032 PetscScalar *v = a->a,*values = (PetscScalar *)advalues; 3033 ISColoringValue *color; 3034 3035 PetscFunctionBegin; 3036 if (!a->coloring) SETERRQ(1,"Coloring not set for matrix"); 3037 color = a->coloring->colors; 3038 /* loop over rows */ 3039 for (i=0; i<m; i++) { 3040 nz = ii[i+1] - ii[i]; 3041 /* loop over columns putting computed value into matrix */ 3042 for (j=0; j<nz; j++) { 3043 *v++ = values[color[*jj++]]; 3044 } 3045 values += nl; /* jump to next row of derivatives */ 3046 } 3047 PetscFunctionReturn(0); 3048 } 3049 3050