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