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