1 #define PETSCMAT_DLL 2 3 4 /* 5 Defines the basic matrix operations for the AIJ (compressed row) 6 matrix storage format. 7 */ 8 9 10 #include "../src/mat/impls/aij/seq/aij.h" /*I "petscmat.h" I*/ 11 #include "petscbt.h" 12 13 #undef __FUNCT__ 14 #define __FUNCT__ "MatDiagonalSet_SeqAIJ" 15 PetscErrorCode PETSCMAT_DLLEXPORT MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is) 16 { 17 PetscErrorCode ierr; 18 Mat_SeqAIJ *aij = (Mat_SeqAIJ*) Y->data; 19 PetscInt i,*diag, m = Y->rmap->n; 20 MatScalar *aa = aij->a; 21 PetscScalar *v; 22 PetscTruth missing; 23 24 PetscFunctionBegin; 25 if (Y->assembled) { 26 ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,PETSC_NULL);CHKERRQ(ierr); 27 if (!missing) { 28 diag = aij->diag; 29 ierr = VecGetArray(D,&v);CHKERRQ(ierr); 30 if (is == INSERT_VALUES) { 31 for (i=0; i<m; i++) { 32 aa[diag[i]] = v[i]; 33 } 34 } else { 35 for (i=0; i<m; i++) { 36 aa[diag[i]] += v[i]; 37 } 38 } 39 ierr = VecRestoreArray(D,&v);CHKERRQ(ierr); 40 PetscFunctionReturn(0); 41 } 42 } 43 ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr); 44 PetscFunctionReturn(0); 45 } 46 47 #undef __FUNCT__ 48 #define __FUNCT__ "MatGetRowIJ_SeqAIJ" 49 PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth inodecompressed,PetscInt *m,PetscInt *ia[],PetscInt *ja[],PetscTruth *done) 50 { 51 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 52 PetscErrorCode ierr; 53 PetscInt i,ishift; 54 55 PetscFunctionBegin; 56 *m = A->rmap->n; 57 if (!ia) PetscFunctionReturn(0); 58 ishift = 0; 59 if (symmetric && !A->structurally_symmetric) { 60 ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,ishift,oshift,ia,ja);CHKERRQ(ierr); 61 } else if (oshift == 1) { 62 PetscInt nz = a->i[A->rmap->n]; 63 /* malloc space and add 1 to i and j indices */ 64 ierr = PetscMalloc((A->rmap->n+1)*sizeof(PetscInt),ia);CHKERRQ(ierr); 65 for (i=0; i<A->rmap->n+1; i++) (*ia)[i] = a->i[i] + 1; 66 if (ja) { 67 ierr = PetscMalloc((nz+1)*sizeof(PetscInt),ja);CHKERRQ(ierr); 68 for (i=0; i<nz; i++) (*ja)[i] = a->j[i] + 1; 69 } 70 } else { 71 *ia = a->i; 72 if (ja) *ja = a->j; 73 } 74 PetscFunctionReturn(0); 75 } 76 77 #undef __FUNCT__ 78 #define __FUNCT__ "MatRestoreRowIJ_SeqAIJ" 79 PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth inodecompressed,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscTruth *done) 80 { 81 PetscErrorCode ierr; 82 83 PetscFunctionBegin; 84 if (!ia) PetscFunctionReturn(0); 85 if ((symmetric && !A->structurally_symmetric) || oshift == 1) { 86 ierr = PetscFree(*ia);CHKERRQ(ierr); 87 if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);} 88 } 89 PetscFunctionReturn(0); 90 } 91 92 #undef __FUNCT__ 93 #define __FUNCT__ "MatGetColumnIJ_SeqAIJ" 94 PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth inodecompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscTruth *done) 95 { 96 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 97 PetscErrorCode ierr; 98 PetscInt i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n; 99 PetscInt nz = a->i[m],row,*jj,mr,col; 100 101 PetscFunctionBegin; 102 *nn = n; 103 if (!ia) PetscFunctionReturn(0); 104 if (symmetric) { 105 ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,0,oshift,ia,ja);CHKERRQ(ierr); 106 } else { 107 ierr = PetscMalloc((n+1)*sizeof(PetscInt),&collengths);CHKERRQ(ierr); 108 ierr = PetscMemzero(collengths,n*sizeof(PetscInt));CHKERRQ(ierr); 109 ierr = PetscMalloc((n+1)*sizeof(PetscInt),&cia);CHKERRQ(ierr); 110 ierr = PetscMalloc((nz+1)*sizeof(PetscInt),&cja);CHKERRQ(ierr); 111 jj = a->j; 112 for (i=0; i<nz; i++) { 113 collengths[jj[i]]++; 114 } 115 cia[0] = oshift; 116 for (i=0; i<n; i++) { 117 cia[i+1] = cia[i] + collengths[i]; 118 } 119 ierr = PetscMemzero(collengths,n*sizeof(PetscInt));CHKERRQ(ierr); 120 jj = a->j; 121 for (row=0; row<m; row++) { 122 mr = a->i[row+1] - a->i[row]; 123 for (i=0; i<mr; i++) { 124 col = *jj++; 125 cja[cia[col] + collengths[col]++ - oshift] = row + oshift; 126 } 127 } 128 ierr = PetscFree(collengths);CHKERRQ(ierr); 129 *ia = cia; *ja = cja; 130 } 131 PetscFunctionReturn(0); 132 } 133 134 #undef __FUNCT__ 135 #define __FUNCT__ "MatRestoreColumnIJ_SeqAIJ" 136 PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth inodecompressed,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscTruth *done) 137 { 138 PetscErrorCode ierr; 139 140 PetscFunctionBegin; 141 if (!ia) PetscFunctionReturn(0); 142 143 ierr = PetscFree(*ia);CHKERRQ(ierr); 144 ierr = PetscFree(*ja);CHKERRQ(ierr); 145 146 PetscFunctionReturn(0); 147 } 148 149 #undef __FUNCT__ 150 #define __FUNCT__ "MatSetValuesRow_SeqAIJ" 151 PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[]) 152 { 153 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 154 PetscInt *ai = a->i; 155 PetscErrorCode ierr; 156 157 PetscFunctionBegin; 158 ierr = PetscMemcpy(a->a+ai[row],v,(ai[row+1]-ai[row])*sizeof(PetscScalar));CHKERRQ(ierr); 159 PetscFunctionReturn(0); 160 } 161 162 #define CHUNKSIZE 15 163 164 #undef __FUNCT__ 165 #define __FUNCT__ "MatSetValues_SeqAIJ" 166 PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is) 167 { 168 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 169 PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N; 170 PetscInt *imax = a->imax,*ai = a->i,*ailen = a->ilen; 171 PetscErrorCode ierr; 172 PetscInt *aj = a->j,nonew = a->nonew,lastcol = -1; 173 MatScalar *ap,value,*aa = a->a; 174 PetscTruth ignorezeroentries = a->ignorezeroentries; 175 PetscTruth roworiented = a->roworiented; 176 177 PetscFunctionBegin; 178 if (v) PetscValidScalarPointer(v,6); 179 for (k=0; k<m; k++) { /* loop over added rows */ 180 row = im[k]; 181 if (row < 0) continue; 182 #if defined(PETSC_USE_DEBUG) 183 if (row >= A->rmap->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1); 184 #endif 185 rp = aj + ai[row]; ap = aa + ai[row]; 186 rmax = imax[row]; nrow = ailen[row]; 187 low = 0; 188 high = nrow; 189 for (l=0; l<n; l++) { /* loop over added columns */ 190 if (in[l] < 0) continue; 191 #if defined(PETSC_USE_DEBUG) 192 if (in[l] >= A->cmap->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1); 193 #endif 194 col = in[l]; 195 if (v) { 196 if (roworiented) { 197 value = v[l + k*n]; 198 } else { 199 value = v[k + l*m]; 200 } 201 } else { 202 value = 0; 203 } 204 if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 205 206 if (col <= lastcol) low = 0; else high = nrow; 207 lastcol = col; 208 while (high-low > 5) { 209 t = (low+high)/2; 210 if (rp[t] > col) high = t; 211 else low = t; 212 } 213 for (i=low; i<high; i++) { 214 if (rp[i] > col) break; 215 if (rp[i] == col) { 216 if (is == ADD_VALUES) ap[i] += value; 217 else ap[i] = value; 218 low = i + 1; 219 goto noinsert; 220 } 221 } 222 if (value == 0.0 && ignorezeroentries) goto noinsert; 223 if (nonew == 1) goto noinsert; 224 if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col); 225 MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar); 226 N = nrow++ - 1; a->nz++; high++; 227 /* shift up all the later entries in this row */ 228 for (ii=N; ii>=i; ii--) { 229 rp[ii+1] = rp[ii]; 230 ap[ii+1] = ap[ii]; 231 } 232 rp[i] = col; 233 ap[i] = value; 234 low = i + 1; 235 noinsert:; 236 } 237 ailen[row] = nrow; 238 } 239 A->same_nonzero = PETSC_FALSE; 240 PetscFunctionReturn(0); 241 } 242 243 244 #undef __FUNCT__ 245 #define __FUNCT__ "MatGetValues_SeqAIJ" 246 PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[]) 247 { 248 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 249 PetscInt *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j; 250 PetscInt *ai = a->i,*ailen = a->ilen; 251 MatScalar *ap,*aa = a->a; 252 253 PetscFunctionBegin; 254 for (k=0; k<m; k++) { /* loop over rows */ 255 row = im[k]; 256 if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */ 257 if (row >= A->rmap->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1); 258 rp = aj + ai[row]; ap = aa + ai[row]; 259 nrow = ailen[row]; 260 for (l=0; l<n; l++) { /* loop over columns */ 261 if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */ 262 if (in[l] >= A->cmap->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1); 263 col = in[l] ; 264 high = nrow; low = 0; /* assume unsorted */ 265 while (high-low > 5) { 266 t = (low+high)/2; 267 if (rp[t] > col) high = t; 268 else low = t; 269 } 270 for (i=low; i<high; i++) { 271 if (rp[i] > col) break; 272 if (rp[i] == col) { 273 *v++ = ap[i]; 274 goto finished; 275 } 276 } 277 *v++ = 0.0; 278 finished:; 279 } 280 } 281 PetscFunctionReturn(0); 282 } 283 284 285 #undef __FUNCT__ 286 #define __FUNCT__ "MatView_SeqAIJ_Binary" 287 PetscErrorCode MatView_SeqAIJ_Binary(Mat A,PetscViewer viewer) 288 { 289 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 290 PetscErrorCode ierr; 291 PetscInt i,*col_lens; 292 int fd; 293 294 PetscFunctionBegin; 295 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 296 ierr = PetscMalloc((4+A->rmap->n)*sizeof(PetscInt),&col_lens);CHKERRQ(ierr); 297 col_lens[0] = MAT_FILE_COOKIE; 298 col_lens[1] = A->rmap->n; 299 col_lens[2] = A->cmap->n; 300 col_lens[3] = a->nz; 301 302 /* store lengths of each row and write (including header) to file */ 303 for (i=0; i<A->rmap->n; i++) { 304 col_lens[4+i] = a->i[i+1] - a->i[i]; 305 } 306 ierr = PetscBinaryWrite(fd,col_lens,4+A->rmap->n,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 307 ierr = PetscFree(col_lens);CHKERRQ(ierr); 308 309 /* store column indices (zero start index) */ 310 ierr = PetscBinaryWrite(fd,a->j,a->nz,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 311 312 /* store nonzero values */ 313 ierr = PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr); 314 PetscFunctionReturn(0); 315 } 316 317 EXTERN PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer); 318 319 #undef __FUNCT__ 320 #define __FUNCT__ "MatView_SeqAIJ_ASCII" 321 PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer) 322 { 323 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 324 PetscErrorCode ierr; 325 PetscInt i,j,m = A->rmap->n,shift=0; 326 const char *name; 327 PetscViewerFormat format; 328 329 PetscFunctionBegin; 330 ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr); 331 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 332 if (format == PETSC_VIEWER_ASCII_MATLAB) { 333 PetscInt nofinalvalue = 0; 334 if ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-!shift)) { 335 nofinalvalue = 1; 336 } 337 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 338 ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr); 339 ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr); 340 ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr); 341 ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr); 342 343 for (i=0; i<m; i++) { 344 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 345 #if defined(PETSC_USE_COMPLEX) 346 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); 347 #else 348 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %18.16e\n",i+1,a->j[j]+!shift,a->a[j]);CHKERRQ(ierr); 349 #endif 350 } 351 } 352 if (nofinalvalue) { 353 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr); 354 } 355 ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr); 356 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 357 } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) { 358 PetscFunctionReturn(0); 359 } else if (format == PETSC_VIEWER_ASCII_COMMON) { 360 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 361 for (i=0; i<m; i++) { 362 ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr); 363 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 364 #if defined(PETSC_USE_COMPLEX) 365 if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) { 366 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 367 } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) { 368 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 369 } else if (PetscRealPart(a->a[j]) != 0.0) { 370 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr); 371 } 372 #else 373 if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);} 374 #endif 375 } 376 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 377 } 378 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 379 } else if (format == PETSC_VIEWER_ASCII_SYMMODU) { 380 PetscInt nzd=0,fshift=1,*sptr; 381 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 382 ierr = PetscMalloc((m+1)*sizeof(PetscInt),&sptr);CHKERRQ(ierr); 383 for (i=0; i<m; i++) { 384 sptr[i] = nzd+1; 385 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 386 if (a->j[j] >= i) { 387 #if defined(PETSC_USE_COMPLEX) 388 if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++; 389 #else 390 if (a->a[j] != 0.0) nzd++; 391 #endif 392 } 393 } 394 } 395 sptr[m] = nzd+1; 396 ierr = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr); 397 for (i=0; i<m+1; i+=6) { 398 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);} 399 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);} 400 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);} 401 else if (i+1<m) {ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);} 402 else if (i<m) {ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);} 403 else {ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);} 404 } 405 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 406 ierr = PetscFree(sptr);CHKERRQ(ierr); 407 for (i=0; i<m; i++) { 408 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 409 if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);} 410 } 411 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 412 } 413 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 414 for (i=0; i<m; i++) { 415 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 416 if (a->j[j] >= i) { 417 #if defined(PETSC_USE_COMPLEX) 418 if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) { 419 ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 420 } 421 #else 422 if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",a->a[j]);CHKERRQ(ierr);} 423 #endif 424 } 425 } 426 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 427 } 428 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 429 } else if (format == PETSC_VIEWER_ASCII_DENSE) { 430 PetscInt cnt = 0,jcnt; 431 PetscScalar value; 432 433 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 434 for (i=0; i<m; i++) { 435 jcnt = 0; 436 for (j=0; j<A->cmap->n; j++) { 437 if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) { 438 value = a->a[cnt++]; 439 jcnt++; 440 } else { 441 value = 0.0; 442 } 443 #if defined(PETSC_USE_COMPLEX) 444 ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",PetscRealPart(value),PetscImaginaryPart(value));CHKERRQ(ierr); 445 #else 446 ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",value);CHKERRQ(ierr); 447 #endif 448 } 449 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 450 } 451 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 452 } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) { 453 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 454 #if defined(PETSC_USE_COMPLEX) 455 ierr = PetscViewerASCIIPrintf(viewer,"%%matrix complex general\n");CHKERRQ(ierr); 456 #else 457 ierr = PetscViewerASCIIPrintf(viewer,"%%matrix real general\n");CHKERRQ(ierr); 458 #endif 459 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr); 460 for (i=0; i<m; i++) { 461 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 462 #if defined(PETSC_USE_COMPLEX) 463 if (PetscImaginaryPart(a->a[j]) > 0.0) { 464 ierr = PetscViewerASCIIPrintf(viewer,"%D %D, %G %G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 465 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 466 ierr = PetscViewerASCIIPrintf(viewer,"%D %D, %G -%G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 467 } else { 468 ierr = PetscViewerASCIIPrintf(viewer,"%D %D, %G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr); 469 } 470 #else 471 ierr = PetscViewerASCIIPrintf(viewer,"%D %D %G\n", i+shift, a->j[j]+shift, a->a[j]);CHKERRQ(ierr); 472 #endif 473 } 474 } 475 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 476 } else { 477 //----------------------------------------------- 478 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr); 479 PetscTruth newdatastruct=PETSC_FALSE,newdatastruct1=PETSC_FALSE; 480 ierr = PetscOptionsGetTruth(PETSC_NULL,"-ilu_new",&newdatastruct,PETSC_NULL);CHKERRQ(ierr); 481 ierr = PetscOptionsGetTruth(PETSC_NULL,"-lu_new",&newdatastruct1,PETSC_NULL);CHKERRQ(ierr); 482 if (A->factor && (newdatastruct || newdatastruct1)){ 483 for (i=0; i<m; i++) { 484 ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr); 485 /* L part */ 486 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 487 #if defined(PETSC_USE_COMPLEX) 488 if (PetscImaginaryPart(a->a[j]) > 0.0) { 489 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 490 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 491 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 492 } else { 493 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr); 494 } 495 #else 496 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr); 497 #endif 498 } 499 /* diagonal */ 500 j = a->diag[i]; 501 #if defined(PETSC_USE_COMPLEX) 502 if (PetscImaginaryPart(a->a[j]) > 0.0) { 503 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 504 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 505 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 506 } else { 507 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr); 508 } 509 #else 510 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr); 511 #endif 512 513 /* U part */ 514 for (j=a->diag[i+1]+1+shift; j<a->diag[i]+shift; j++) { 515 #if defined(PETSC_USE_COMPLEX) 516 if (PetscImaginaryPart(a->a[j]) > 0.0) { 517 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 518 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 519 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 520 } else { 521 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr); 522 } 523 #else 524 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr); 525 #endif 526 } 527 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 528 } 529 // The test example: petsc-dev/src/mat/examples/tests/ex30.c 530 //---------------------------------------------- 531 } else { 532 for (i=0; i<m; i++) { 533 ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr); 534 for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) { 535 #if defined(PETSC_USE_COMPLEX) 536 if (PetscImaginaryPart(a->a[j]) > 0.0) { 537 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 538 } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 539 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr); 540 } else { 541 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr); 542 } 543 #else 544 ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr); 545 #endif 546 } 547 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 548 } 549 } 550 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr); 551 } 552 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 553 PetscFunctionReturn(0); 554 } 555 556 #undef __FUNCT__ 557 #define __FUNCT__ "MatView_SeqAIJ_Draw_Zoom" 558 PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa) 559 { 560 Mat A = (Mat) Aa; 561 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 562 PetscErrorCode ierr; 563 PetscInt i,j,m = A->rmap->n,color; 564 PetscReal xl,yl,xr,yr,x_l,x_r,y_l,y_r,maxv = 0.0; 565 PetscViewer viewer; 566 PetscViewerFormat format; 567 568 PetscFunctionBegin; 569 ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr); 570 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 571 572 ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 573 /* loop over matrix elements drawing boxes */ 574 575 if (format != PETSC_VIEWER_DRAW_CONTOUR) { 576 /* Blue for negative, Cyan for zero and Red for positive */ 577 color = PETSC_DRAW_BLUE; 578 for (i=0; i<m; i++) { 579 y_l = m - i - 1.0; y_r = y_l + 1.0; 580 for (j=a->i[i]; j<a->i[i+1]; j++) { 581 x_l = a->j[j] ; x_r = x_l + 1.0; 582 #if defined(PETSC_USE_COMPLEX) 583 if (PetscRealPart(a->a[j]) >= 0.) continue; 584 #else 585 if (a->a[j] >= 0.) continue; 586 #endif 587 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 588 } 589 } 590 color = PETSC_DRAW_CYAN; 591 for (i=0; i<m; i++) { 592 y_l = m - i - 1.0; y_r = y_l + 1.0; 593 for (j=a->i[i]; j<a->i[i+1]; j++) { 594 x_l = a->j[j]; x_r = x_l + 1.0; 595 if (a->a[j] != 0.) continue; 596 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 597 } 598 } 599 color = PETSC_DRAW_RED; 600 for (i=0; i<m; i++) { 601 y_l = m - i - 1.0; y_r = y_l + 1.0; 602 for (j=a->i[i]; j<a->i[i+1]; j++) { 603 x_l = a->j[j]; x_r = x_l + 1.0; 604 #if defined(PETSC_USE_COMPLEX) 605 if (PetscRealPart(a->a[j]) <= 0.) continue; 606 #else 607 if (a->a[j] <= 0.) continue; 608 #endif 609 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 610 } 611 } 612 } else { 613 /* use contour shading to indicate magnitude of values */ 614 /* first determine max of all nonzero values */ 615 PetscInt nz = a->nz,count; 616 PetscDraw popup; 617 PetscReal scale; 618 619 for (i=0; i<nz; i++) { 620 if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]); 621 } 622 scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/maxv; 623 ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr); 624 if (popup) {ierr = PetscDrawScalePopup(popup,0.0,maxv);CHKERRQ(ierr);} 625 count = 0; 626 for (i=0; i<m; i++) { 627 y_l = m - i - 1.0; y_r = y_l + 1.0; 628 for (j=a->i[i]; j<a->i[i+1]; j++) { 629 x_l = a->j[j]; x_r = x_l + 1.0; 630 color = PETSC_DRAW_BASIC_COLORS + (PetscInt)(scale*PetscAbsScalar(a->a[count])); 631 ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr); 632 count++; 633 } 634 } 635 } 636 PetscFunctionReturn(0); 637 } 638 639 #undef __FUNCT__ 640 #define __FUNCT__ "MatView_SeqAIJ_Draw" 641 PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer) 642 { 643 PetscErrorCode ierr; 644 PetscDraw draw; 645 PetscReal xr,yr,xl,yl,h,w; 646 PetscTruth isnull; 647 648 PetscFunctionBegin; 649 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 650 ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); 651 if (isnull) PetscFunctionReturn(0); 652 653 ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr); 654 xr = A->cmap->n; yr = A->rmap->n; h = yr/10.0; w = xr/10.0; 655 xr += w; yr += h; xl = -w; yl = -h; 656 ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr); 657 ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr); 658 ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr); 659 PetscFunctionReturn(0); 660 } 661 662 #undef __FUNCT__ 663 #define __FUNCT__ "MatView_SeqAIJ" 664 PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer) 665 { 666 PetscErrorCode ierr; 667 PetscTruth iascii,isbinary,isdraw; 668 669 PetscFunctionBegin; 670 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 671 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);CHKERRQ(ierr); 672 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr); 673 if (iascii) { 674 ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr); 675 } else if (isbinary) { 676 ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr); 677 } else if (isdraw) { 678 ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr); 679 } else { 680 SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by SeqAIJ matrices",((PetscObject)viewer)->type_name); 681 } 682 ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr); 683 PetscFunctionReturn(0); 684 } 685 686 #undef __FUNCT__ 687 #define __FUNCT__ "MatAssemblyEnd_SeqAIJ" 688 PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode) 689 { 690 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 691 PetscErrorCode ierr; 692 PetscInt fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax; 693 PetscInt m = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0; 694 MatScalar *aa = a->a,*ap; 695 PetscReal ratio=0.6; 696 697 PetscFunctionBegin; 698 if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 699 700 if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 701 for (i=1; i<m; i++) { 702 /* move each row back by the amount of empty slots (fshift) before it*/ 703 fshift += imax[i-1] - ailen[i-1]; 704 rmax = PetscMax(rmax,ailen[i]); 705 if (fshift) { 706 ip = aj + ai[i] ; 707 ap = aa + ai[i] ; 708 N = ailen[i]; 709 for (j=0; j<N; j++) { 710 ip[j-fshift] = ip[j]; 711 ap[j-fshift] = ap[j]; 712 } 713 } 714 ai[i] = ai[i-1] + ailen[i-1]; 715 } 716 if (m) { 717 fshift += imax[m-1] - ailen[m-1]; 718 ai[m] = ai[m-1] + ailen[m-1]; 719 } 720 /* reset ilen and imax for each row */ 721 for (i=0; i<m; i++) { 722 ailen[i] = imax[i] = ai[i+1] - ai[i]; 723 } 724 a->nz = ai[m]; 725 if (fshift && a->nounused == -1) { 726 SETERRQ3(PETSC_ERR_PLIB, "Unused space detected in matrix: %D X %D, %D unneeded", m, A->cmap->n, fshift); 727 } 728 729 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 730 ierr = PetscInfo4(A,"Matrix size: %D X %D; storage space: %D unneeded,%D used\n",m,A->cmap->n,fshift,a->nz);CHKERRQ(ierr); 731 ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr); 732 ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr); 733 734 a->reallocs = 0; 735 A->info.nz_unneeded = (double)fshift; 736 a->rmax = rmax; 737 738 /* check for zero rows. If found a large number of zero rows, use CompressedRow functions */ 739 ierr = Mat_CheckCompressedRow(A,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr); 740 A->same_nonzero = PETSC_TRUE; 741 742 ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr); 743 744 a->idiagvalid = PETSC_FALSE; 745 PetscFunctionReturn(0); 746 } 747 748 #undef __FUNCT__ 749 #define __FUNCT__ "MatRealPart_SeqAIJ" 750 PetscErrorCode MatRealPart_SeqAIJ(Mat A) 751 { 752 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 753 PetscInt i,nz = a->nz; 754 MatScalar *aa = a->a; 755 756 PetscFunctionBegin; 757 for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]); 758 PetscFunctionReturn(0); 759 } 760 761 #undef __FUNCT__ 762 #define __FUNCT__ "MatImaginaryPart_SeqAIJ" 763 PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A) 764 { 765 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 766 PetscInt i,nz = a->nz; 767 MatScalar *aa = a->a; 768 769 PetscFunctionBegin; 770 for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]); 771 PetscFunctionReturn(0); 772 } 773 774 #undef __FUNCT__ 775 #define __FUNCT__ "MatZeroEntries_SeqAIJ" 776 PetscErrorCode MatZeroEntries_SeqAIJ(Mat A) 777 { 778 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 779 PetscErrorCode ierr; 780 781 PetscFunctionBegin; 782 ierr = PetscMemzero(a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));CHKERRQ(ierr); 783 PetscFunctionReturn(0); 784 } 785 786 #undef __FUNCT__ 787 #define __FUNCT__ "MatDestroy_SeqAIJ" 788 PetscErrorCode MatDestroy_SeqAIJ(Mat A) 789 { 790 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 791 PetscErrorCode ierr; 792 793 PetscFunctionBegin; 794 #if defined(PETSC_USE_LOG) 795 PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz); 796 #endif 797 ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr); 798 if (a->row) { 799 ierr = ISDestroy(a->row);CHKERRQ(ierr); 800 } 801 if (a->col) { 802 ierr = ISDestroy(a->col);CHKERRQ(ierr); 803 } 804 ierr = PetscFree(a->diag);CHKERRQ(ierr); 805 ierr = PetscFree2(a->imax,a->ilen);CHKERRQ(ierr); 806 ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr); 807 ierr = PetscFree(a->solve_work);CHKERRQ(ierr); 808 if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);} 809 ierr = PetscFree(a->saved_values);CHKERRQ(ierr); 810 if (a->coloring) {ierr = ISColoringDestroy(a->coloring);CHKERRQ(ierr);} 811 ierr = PetscFree(a->xtoy);CHKERRQ(ierr); 812 if (a->XtoY) {ierr = MatDestroy(a->XtoY);CHKERRQ(ierr);} 813 if (a->compressedrow.checked && a->compressedrow.use){ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);} 814 815 ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr); 816 817 ierr = PetscFree(a);CHKERRQ(ierr); 818 819 ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 820 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetColumnIndices_C","",PETSC_NULL);CHKERRQ(ierr); 821 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatStoreValues_C","",PETSC_NULL);CHKERRQ(ierr); 822 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatRetrieveValues_C","",PETSC_NULL);CHKERRQ(ierr); 823 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqsbaij_C","",PETSC_NULL);CHKERRQ(ierr); 824 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqbaij_C","",PETSC_NULL);CHKERRQ(ierr); 825 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqcsrperm_C","",PETSC_NULL);CHKERRQ(ierr); 826 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatIsTranspose_C","",PETSC_NULL);CHKERRQ(ierr); 827 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocation_C","",PETSC_NULL);CHKERRQ(ierr); 828 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C","",PETSC_NULL);CHKERRQ(ierr); 829 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatReorderForNonzeroDiagonal_C","",PETSC_NULL);CHKERRQ(ierr); 830 PetscFunctionReturn(0); 831 } 832 833 #undef __FUNCT__ 834 #define __FUNCT__ "MatSetOption_SeqAIJ" 835 PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscTruth flg) 836 { 837 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 838 PetscErrorCode ierr; 839 840 PetscFunctionBegin; 841 switch (op) { 842 case MAT_ROW_ORIENTED: 843 a->roworiented = flg; 844 break; 845 case MAT_KEEP_NONZERO_PATTERN: 846 a->keepnonzeropattern = flg; 847 break; 848 case MAT_NEW_NONZERO_LOCATIONS: 849 a->nonew = (flg ? 0 : 1); 850 break; 851 case MAT_NEW_NONZERO_LOCATION_ERR: 852 a->nonew = (flg ? -1 : 0); 853 break; 854 case MAT_NEW_NONZERO_ALLOCATION_ERR: 855 a->nonew = (flg ? -2 : 0); 856 break; 857 case MAT_UNUSED_NONZERO_LOCATION_ERR: 858 a->nounused = (flg ? -1 : 0); 859 break; 860 case MAT_IGNORE_ZERO_ENTRIES: 861 a->ignorezeroentries = flg; 862 break; 863 case MAT_USE_COMPRESSEDROW: 864 a->compressedrow.use = flg; 865 break; 866 case MAT_NEW_DIAGONALS: 867 case MAT_IGNORE_OFF_PROC_ENTRIES: 868 case MAT_USE_HASH_TABLE: 869 ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr); 870 break; 871 default: 872 break; 873 } 874 ierr = MatSetOption_SeqAIJ_Inode(A,op,flg);CHKERRQ(ierr); 875 PetscFunctionReturn(0); 876 } 877 878 #undef __FUNCT__ 879 #define __FUNCT__ "MatGetDiagonal_SeqAIJ" 880 PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v) 881 { 882 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 883 PetscErrorCode ierr; 884 PetscInt i,j,n; 885 PetscScalar *x,zero = 0.0; 886 887 PetscFunctionBegin; 888 ierr = VecSet(v,zero);CHKERRQ(ierr); 889 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 890 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 891 if (n != A->rmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 892 for (i=0; i<A->rmap->n; i++) { 893 for (j=a->i[i]; j<a->i[i+1]; j++) { 894 if (a->j[j] == i) { 895 x[i] = a->a[j]; 896 break; 897 } 898 } 899 } 900 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 901 PetscFunctionReturn(0); 902 } 903 904 #include "../src/mat/impls/aij/seq/ftn-kernels/fmult.h" 905 #undef __FUNCT__ 906 #define __FUNCT__ "MatMultTransposeAdd_SeqAIJ" 907 PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy) 908 { 909 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 910 PetscScalar *x,*y; 911 PetscErrorCode ierr; 912 PetscInt m = A->rmap->n; 913 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 914 MatScalar *v; 915 PetscScalar alpha; 916 PetscInt n,i,j,*idx,*ii,*ridx=PETSC_NULL; 917 Mat_CompressedRow cprow = a->compressedrow; 918 PetscTruth usecprow = cprow.use; 919 #endif 920 921 PetscFunctionBegin; 922 if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);} 923 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 924 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 925 926 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 927 fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y); 928 #else 929 if (usecprow){ 930 m = cprow.nrows; 931 ii = cprow.i; 932 ridx = cprow.rindex; 933 } else { 934 ii = a->i; 935 } 936 for (i=0; i<m; i++) { 937 idx = a->j + ii[i] ; 938 v = a->a + ii[i] ; 939 n = ii[i+1] - ii[i]; 940 if (usecprow){ 941 alpha = x[ridx[i]]; 942 } else { 943 alpha = x[i]; 944 } 945 for (j=0; j<n; j++) y[idx[j]] += alpha*v[j]; 946 } 947 #endif 948 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 949 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 950 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 951 PetscFunctionReturn(0); 952 } 953 954 #undef __FUNCT__ 955 #define __FUNCT__ "MatMultTranspose_SeqAIJ" 956 PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy) 957 { 958 PetscErrorCode ierr; 959 960 PetscFunctionBegin; 961 ierr = VecSet(yy,0.0);CHKERRQ(ierr); 962 ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr); 963 PetscFunctionReturn(0); 964 } 965 966 #include "../src/mat/impls/aij/seq/ftn-kernels/fmult.h" 967 #undef __FUNCT__ 968 #define __FUNCT__ "MatMult_SeqAIJ" 969 PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy) 970 { 971 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 972 PetscScalar *y; 973 const PetscScalar *x; 974 const MatScalar *aa; 975 PetscErrorCode ierr; 976 PetscInt m=A->rmap->n; 977 const PetscInt *aj,*ii,*ridx=PETSC_NULL; 978 PetscInt n,i,nonzerorow=0; 979 PetscScalar sum; 980 PetscTruth usecprow=a->compressedrow.use; 981 982 #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 983 #pragma disjoint(*x,*y,*aa) 984 #endif 985 986 PetscFunctionBegin; 987 ierr = VecGetArray(xx,(PetscScalar**)&x);CHKERRQ(ierr); 988 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 989 aj = a->j; 990 aa = a->a; 991 ii = a->i; 992 if (usecprow){ /* use compressed row format */ 993 m = a->compressedrow.nrows; 994 ii = a->compressedrow.i; 995 ridx = a->compressedrow.rindex; 996 for (i=0; i<m; i++){ 997 n = ii[i+1] - ii[i]; 998 aj = a->j + ii[i]; 999 aa = a->a + ii[i]; 1000 sum = 0.0; 1001 nonzerorow += (n>0); 1002 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1003 /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 1004 y[*ridx++] = sum; 1005 } 1006 } else { /* do not use compressed row format */ 1007 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ) 1008 fortranmultaij_(&m,x,ii,aj,aa,y); 1009 #else 1010 for (i=0; i<m; i++) { 1011 n = ii[i+1] - ii[i]; 1012 aj = a->j + ii[i]; 1013 aa = a->a + ii[i]; 1014 sum = 0.0; 1015 nonzerorow += (n>0); 1016 PetscSparseDensePlusDot(sum,x,aa,aj,n); 1017 y[i] = sum; 1018 } 1019 #endif 1020 } 1021 ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr); 1022 ierr = VecRestoreArray(xx,(PetscScalar**)&x);CHKERRQ(ierr); 1023 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 1024 PetscFunctionReturn(0); 1025 } 1026 1027 #include "../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h" 1028 #undef __FUNCT__ 1029 #define __FUNCT__ "MatMultAdd_SeqAIJ" 1030 PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1031 { 1032 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1033 PetscScalar *x,*y,*z; 1034 const MatScalar *aa; 1035 PetscErrorCode ierr; 1036 PetscInt m = A->rmap->n,*aj,*ii; 1037 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ) 1038 PetscInt n,i,jrow,j,*ridx=PETSC_NULL; 1039 PetscScalar sum; 1040 PetscTruth usecprow=a->compressedrow.use; 1041 #endif 1042 1043 PetscFunctionBegin; 1044 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 1045 ierr = VecGetArray(yy,&y);CHKERRQ(ierr); 1046 if (zz != yy) { 1047 ierr = VecGetArray(zz,&z);CHKERRQ(ierr); 1048 } else { 1049 z = y; 1050 } 1051 1052 aj = a->j; 1053 aa = a->a; 1054 ii = a->i; 1055 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ) 1056 fortranmultaddaij_(&m,x,ii,aj,aa,y,z); 1057 #else 1058 if (usecprow){ /* use compressed row format */ 1059 if (zz != yy){ 1060 ierr = PetscMemcpy(z,y,m*sizeof(PetscScalar));CHKERRQ(ierr); 1061 } 1062 m = a->compressedrow.nrows; 1063 ii = a->compressedrow.i; 1064 ridx = a->compressedrow.rindex; 1065 for (i=0; i<m; i++){ 1066 n = ii[i+1] - ii[i]; 1067 aj = a->j + ii[i]; 1068 aa = a->a + ii[i]; 1069 sum = y[*ridx]; 1070 for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; 1071 z[*ridx++] = sum; 1072 } 1073 } else { /* do not use compressed row format */ 1074 for (i=0; i<m; i++) { 1075 jrow = ii[i]; 1076 n = ii[i+1] - jrow; 1077 sum = y[i]; 1078 for (j=0; j<n; j++) { 1079 sum += aa[jrow]*x[aj[jrow]]; jrow++; 1080 } 1081 z[i] = sum; 1082 } 1083 } 1084 #endif 1085 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1086 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1087 ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr); 1088 if (zz != yy) { 1089 ierr = VecRestoreArray(zz,&z);CHKERRQ(ierr); 1090 } 1091 PetscFunctionReturn(0); 1092 } 1093 1094 /* 1095 Adds diagonal pointers to sparse matrix structure. 1096 */ 1097 #undef __FUNCT__ 1098 #define __FUNCT__ "MatMarkDiagonal_SeqAIJ" 1099 PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A) 1100 { 1101 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1102 PetscErrorCode ierr; 1103 PetscInt i,j,m = A->rmap->n; 1104 1105 PetscFunctionBegin; 1106 if (!a->diag) { 1107 ierr = PetscMalloc(m*sizeof(PetscInt),&a->diag);CHKERRQ(ierr); 1108 ierr = PetscLogObjectMemory(A, m*sizeof(PetscInt));CHKERRQ(ierr); 1109 } 1110 for (i=0; i<A->rmap->n; i++) { 1111 a->diag[i] = a->i[i+1]; 1112 for (j=a->i[i]; j<a->i[i+1]; j++) { 1113 if (a->j[j] == i) { 1114 a->diag[i] = j; 1115 break; 1116 } 1117 } 1118 } 1119 PetscFunctionReturn(0); 1120 } 1121 1122 /* 1123 Checks for missing diagonals 1124 */ 1125 #undef __FUNCT__ 1126 #define __FUNCT__ "MatMissingDiagonal_SeqAIJ" 1127 PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscTruth *missing,PetscInt *d) 1128 { 1129 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1130 PetscInt *diag,*jj = a->j,i; 1131 1132 PetscFunctionBegin; 1133 *missing = PETSC_FALSE; 1134 if (A->rmap->n > 0 && !jj) { 1135 *missing = PETSC_TRUE; 1136 if (d) *d = 0; 1137 PetscInfo(A,"Matrix has no entries therefor is missing diagonal"); 1138 } else { 1139 diag = a->diag; 1140 for (i=0; i<A->rmap->n; i++) { 1141 if (jj[diag[i]] != i) { 1142 *missing = PETSC_TRUE; 1143 if (d) *d = i; 1144 PetscInfo1(A,"Matrix is missing diagonal number %D",i); 1145 } 1146 } 1147 } 1148 PetscFunctionReturn(0); 1149 } 1150 1151 EXTERN_C_BEGIN 1152 #undef __FUNCT__ 1153 #define __FUNCT__ "MatInvertDiagonal_SeqAIJ" 1154 PetscErrorCode PETSCMAT_DLLEXPORT MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift) 1155 { 1156 Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 1157 PetscErrorCode ierr; 1158 PetscInt i,*diag,m = A->rmap->n; 1159 MatScalar *v = a->a; 1160 PetscScalar *idiag,*mdiag; 1161 1162 PetscFunctionBegin; 1163 if (a->idiagvalid) PetscFunctionReturn(0); 1164 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 1165 diag = a->diag; 1166 if (!a->idiag) { 1167 ierr = PetscMalloc3(m,PetscScalar,&a->idiag,m,PetscScalar,&a->mdiag,m,PetscScalar,&a->ssor_work);CHKERRQ(ierr); 1168 ierr = PetscLogObjectMemory(A, 3*m*sizeof(PetscScalar));CHKERRQ(ierr); 1169 v = a->a; 1170 } 1171 mdiag = a->mdiag; 1172 idiag = a->idiag; 1173 1174 if (omega == 1.0 && !PetscAbsScalar(fshift)) { 1175 for (i=0; i<m; i++) { 1176 mdiag[i] = v[diag[i]]; 1177 if (!PetscAbsScalar(mdiag[i])) SETERRQ1(PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i); 1178 idiag[i] = 1.0/v[diag[i]]; 1179 } 1180 ierr = PetscLogFlops(m);CHKERRQ(ierr); 1181 } else { 1182 for (i=0; i<m; i++) { 1183 mdiag[i] = v[diag[i]]; 1184 idiag[i] = omega/(fshift + v[diag[i]]); 1185 } 1186 ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr); 1187 } 1188 a->idiagvalid = PETSC_TRUE; 1189 PetscFunctionReturn(0); 1190 } 1191 EXTERN_C_END 1192 1193 #include "../src/mat/impls/aij/seq/ftn-kernels/frelax.h" 1194 #undef __FUNCT__ 1195 #define __FUNCT__ "MatSOR_SeqAIJ" 1196 PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 1197 { 1198 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1199 PetscScalar *x,d,sum,*t,scale; 1200 const MatScalar *v = a->a,*idiag=0,*mdiag; 1201 const PetscScalar *b, *bs,*xb, *ts; 1202 PetscErrorCode ierr; 1203 PetscInt n = A->cmap->n,m = A->rmap->n,i; 1204 const PetscInt *idx,*diag; 1205 1206 PetscFunctionBegin; 1207 its = its*lits; 1208 1209 if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */ 1210 if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);} 1211 a->fshift = fshift; 1212 a->omega = omega; 1213 1214 diag = a->diag; 1215 t = a->ssor_work; 1216 idiag = a->idiag; 1217 mdiag = a->mdiag; 1218 1219 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 1220 if (xx != bb) { 1221 ierr = VecGetArray(bb,(PetscScalar**)&b);CHKERRQ(ierr); 1222 } else { 1223 b = x; 1224 } 1225 CHKMEMQ; 1226 /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */ 1227 if (flag == SOR_APPLY_UPPER) { 1228 /* apply (U + D/omega) to the vector */ 1229 bs = b; 1230 for (i=0; i<m; i++) { 1231 d = fshift + mdiag[i]; 1232 n = a->i[i+1] - diag[i] - 1; 1233 idx = a->j + diag[i] + 1; 1234 v = a->a + diag[i] + 1; 1235 sum = b[i]*d/omega; 1236 PetscSparseDensePlusDot(sum,bs,v,idx,n); 1237 x[i] = sum; 1238 } 1239 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1240 if (bb != xx) {ierr = VecRestoreArray(bb,(PetscScalar**)&b);CHKERRQ(ierr);} 1241 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 1242 PetscFunctionReturn(0); 1243 } 1244 1245 if (flag == SOR_APPLY_LOWER) { 1246 SETERRQ(PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented"); 1247 } else if (flag & SOR_EISENSTAT) { 1248 /* Let A = L + U + D; where L is lower trianglar, 1249 U is upper triangular, E = D/omega; This routine applies 1250 1251 (L + E)^{-1} A (U + E)^{-1} 1252 1253 to a vector efficiently using Eisenstat's trick. 1254 */ 1255 scale = (2.0/omega) - 1.0; 1256 1257 /* x = (E + U)^{-1} b */ 1258 for (i=m-1; i>=0; i--) { 1259 n = a->i[i+1] - diag[i] - 1; 1260 idx = a->j + diag[i] + 1; 1261 v = a->a + diag[i] + 1; 1262 sum = b[i]; 1263 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1264 x[i] = sum*idiag[i]; 1265 } 1266 1267 /* t = b - (2*E - D)x */ 1268 v = a->a; 1269 for (i=0; i<m; i++) { t[i] = b[i] - scale*(v[*diag++])*x[i]; } 1270 1271 /* t = (E + L)^{-1}t */ 1272 ts = t; 1273 diag = a->diag; 1274 for (i=0; i<m; i++) { 1275 n = diag[i] - a->i[i]; 1276 idx = a->j + a->i[i]; 1277 v = a->a + a->i[i]; 1278 sum = t[i]; 1279 PetscSparseDenseMinusDot(sum,ts,v,idx,n); 1280 t[i] = sum*idiag[i]; 1281 /* x = x + t */ 1282 x[i] += t[i]; 1283 } 1284 1285 ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr); 1286 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1287 if (bb != xx) {ierr = VecRestoreArray(bb,(PetscScalar**)&b);CHKERRQ(ierr);} 1288 PetscFunctionReturn(0); 1289 } 1290 if (flag & SOR_ZERO_INITIAL_GUESS) { 1291 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 1292 for (i=0; i<m; i++) { 1293 n = diag[i] - a->i[i]; 1294 idx = a->j + a->i[i]; 1295 v = a->a + a->i[i]; 1296 sum = b[i]; 1297 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1298 t[i] = sum; 1299 x[i] = sum*idiag[i]; 1300 } 1301 xb = t; 1302 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 1303 } else xb = b; 1304 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 1305 for (i=m-1; i>=0; i--) { 1306 n = a->i[i+1] - diag[i] - 1; 1307 idx = a->j + diag[i] + 1; 1308 v = a->a + diag[i] + 1; 1309 sum = xb[i]; 1310 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1311 if (xb == b) { 1312 x[i] = sum*idiag[i]; 1313 } else { 1314 x[i] = (1-omega)*x[i] + sum*idiag[i]; 1315 } 1316 } 1317 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 1318 } 1319 its--; 1320 } 1321 while (its--) { 1322 if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){ 1323 for (i=0; i<m; i++) { 1324 n = a->i[i+1] - a->i[i]; 1325 idx = a->j + a->i[i]; 1326 v = a->a + a->i[i]; 1327 sum = b[i]; 1328 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1329 x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i]; 1330 } 1331 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1332 } 1333 if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){ 1334 for (i=m-1; i>=0; i--) { 1335 n = a->i[i+1] - a->i[i]; 1336 idx = a->j + a->i[i]; 1337 v = a->a + a->i[i]; 1338 sum = b[i]; 1339 PetscSparseDenseMinusDot(sum,x,v,idx,n); 1340 x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i]; 1341 } 1342 ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr); 1343 } 1344 } 1345 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 1346 if (bb != xx) {ierr = VecRestoreArray(bb,(PetscScalar**)&b);CHKERRQ(ierr);} 1347 CHKMEMQ; PetscFunctionReturn(0); 1348 } 1349 1350 1351 #undef __FUNCT__ 1352 #define __FUNCT__ "MatGetInfo_SeqAIJ" 1353 PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info) 1354 { 1355 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1356 1357 PetscFunctionBegin; 1358 info->block_size = 1.0; 1359 info->nz_allocated = (double)a->maxnz; 1360 info->nz_used = (double)a->nz; 1361 info->nz_unneeded = (double)(a->maxnz - a->nz); 1362 info->assemblies = (double)A->num_ass; 1363 info->mallocs = (double)a->reallocs; 1364 info->memory = ((PetscObject)A)->mem; 1365 if (A->factor) { 1366 info->fill_ratio_given = A->info.fill_ratio_given; 1367 info->fill_ratio_needed = A->info.fill_ratio_needed; 1368 info->factor_mallocs = A->info.factor_mallocs; 1369 } else { 1370 info->fill_ratio_given = 0; 1371 info->fill_ratio_needed = 0; 1372 info->factor_mallocs = 0; 1373 } 1374 PetscFunctionReturn(0); 1375 } 1376 1377 #undef __FUNCT__ 1378 #define __FUNCT__ "MatZeroRows_SeqAIJ" 1379 PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag) 1380 { 1381 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1382 PetscInt i,m = A->rmap->n - 1,d; 1383 PetscErrorCode ierr; 1384 PetscTruth missing; 1385 1386 PetscFunctionBegin; 1387 if (a->keepnonzeropattern) { 1388 for (i=0; i<N; i++) { 1389 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 1390 ierr = PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));CHKERRQ(ierr); 1391 } 1392 if (diag != 0.0) { 1393 ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr); 1394 if (missing) SETERRQ1(PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D",d); 1395 for (i=0; i<N; i++) { 1396 a->a[a->diag[rows[i]]] = diag; 1397 } 1398 } 1399 A->same_nonzero = PETSC_TRUE; 1400 } else { 1401 if (diag != 0.0) { 1402 for (i=0; i<N; i++) { 1403 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 1404 if (a->ilen[rows[i]] > 0) { 1405 a->ilen[rows[i]] = 1; 1406 a->a[a->i[rows[i]]] = diag; 1407 a->j[a->i[rows[i]]] = rows[i]; 1408 } else { /* in case row was completely empty */ 1409 ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr); 1410 } 1411 } 1412 } else { 1413 for (i=0; i<N; i++) { 1414 if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]); 1415 a->ilen[rows[i]] = 0; 1416 } 1417 } 1418 A->same_nonzero = PETSC_FALSE; 1419 } 1420 ierr = MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1421 PetscFunctionReturn(0); 1422 } 1423 1424 #undef __FUNCT__ 1425 #define __FUNCT__ "MatGetRow_SeqAIJ" 1426 PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 1427 { 1428 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1429 PetscInt *itmp; 1430 1431 PetscFunctionBegin; 1432 if (row < 0 || row >= A->rmap->n) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row); 1433 1434 *nz = a->i[row+1] - a->i[row]; 1435 if (v) *v = a->a + a->i[row]; 1436 if (idx) { 1437 itmp = a->j + a->i[row]; 1438 if (*nz) { 1439 *idx = itmp; 1440 } 1441 else *idx = 0; 1442 } 1443 PetscFunctionReturn(0); 1444 } 1445 1446 /* remove this function? */ 1447 #undef __FUNCT__ 1448 #define __FUNCT__ "MatRestoreRow_SeqAIJ" 1449 PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 1450 { 1451 PetscFunctionBegin; 1452 PetscFunctionReturn(0); 1453 } 1454 1455 #undef __FUNCT__ 1456 #define __FUNCT__ "MatNorm_SeqAIJ" 1457 PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm) 1458 { 1459 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1460 MatScalar *v = a->a; 1461 PetscReal sum = 0.0; 1462 PetscErrorCode ierr; 1463 PetscInt i,j; 1464 1465 PetscFunctionBegin; 1466 if (type == NORM_FROBENIUS) { 1467 for (i=0; i<a->nz; i++) { 1468 #if defined(PETSC_USE_COMPLEX) 1469 sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 1470 #else 1471 sum += (*v)*(*v); v++; 1472 #endif 1473 } 1474 *nrm = sqrt(sum); 1475 } else if (type == NORM_1) { 1476 PetscReal *tmp; 1477 PetscInt *jj = a->j; 1478 ierr = PetscMalloc((A->cmap->n+1)*sizeof(PetscReal),&tmp);CHKERRQ(ierr); 1479 ierr = PetscMemzero(tmp,A->cmap->n*sizeof(PetscReal));CHKERRQ(ierr); 1480 *nrm = 0.0; 1481 for (j=0; j<a->nz; j++) { 1482 tmp[*jj++] += PetscAbsScalar(*v); v++; 1483 } 1484 for (j=0; j<A->cmap->n; j++) { 1485 if (tmp[j] > *nrm) *nrm = tmp[j]; 1486 } 1487 ierr = PetscFree(tmp);CHKERRQ(ierr); 1488 } else if (type == NORM_INFINITY) { 1489 *nrm = 0.0; 1490 for (j=0; j<A->rmap->n; j++) { 1491 v = a->a + a->i[j]; 1492 sum = 0.0; 1493 for (i=0; i<a->i[j+1]-a->i[j]; i++) { 1494 sum += PetscAbsScalar(*v); v++; 1495 } 1496 if (sum > *nrm) *nrm = sum; 1497 } 1498 } else { 1499 SETERRQ(PETSC_ERR_SUP,"No support for two norm"); 1500 } 1501 PetscFunctionReturn(0); 1502 } 1503 1504 #undef __FUNCT__ 1505 #define __FUNCT__ "MatTranspose_SeqAIJ" 1506 PetscErrorCode MatTranspose_SeqAIJ(Mat A,MatReuse reuse,Mat *B) 1507 { 1508 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1509 Mat C; 1510 PetscErrorCode ierr; 1511 PetscInt i,*aj = a->j,*ai = a->i,m = A->rmap->n,len,*col; 1512 MatScalar *array = a->a; 1513 1514 PetscFunctionBegin; 1515 if (reuse == MAT_REUSE_MATRIX && A == *B && m != A->cmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Square matrix only for in-place"); 1516 1517 if (reuse == MAT_INITIAL_MATRIX || *B == A) { 1518 ierr = PetscMalloc((1+A->cmap->n)*sizeof(PetscInt),&col);CHKERRQ(ierr); 1519 ierr = PetscMemzero(col,(1+A->cmap->n)*sizeof(PetscInt));CHKERRQ(ierr); 1520 1521 for (i=0; i<ai[m]; i++) col[aj[i]] += 1; 1522 ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr); 1523 ierr = MatSetSizes(C,A->cmap->n,m,A->cmap->n,m);CHKERRQ(ierr); 1524 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 1525 ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,col);CHKERRQ(ierr); 1526 ierr = PetscFree(col);CHKERRQ(ierr); 1527 } else { 1528 C = *B; 1529 } 1530 1531 for (i=0; i<m; i++) { 1532 len = ai[i+1]-ai[i]; 1533 ierr = MatSetValues_SeqAIJ(C,len,aj,1,&i,array,INSERT_VALUES);CHKERRQ(ierr); 1534 array += len; 1535 aj += len; 1536 } 1537 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1538 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1539 1540 if (reuse == MAT_INITIAL_MATRIX || *B != A) { 1541 *B = C; 1542 } else { 1543 ierr = MatHeaderCopy(A,C);CHKERRQ(ierr); 1544 } 1545 PetscFunctionReturn(0); 1546 } 1547 1548 EXTERN_C_BEGIN 1549 #undef __FUNCT__ 1550 #define __FUNCT__ "MatIsTranspose_SeqAIJ" 1551 PetscErrorCode PETSCMAT_DLLEXPORT MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscTruth *f) 1552 { 1553 Mat_SeqAIJ *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data; 1554 PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr; 1555 MatScalar *va,*vb; 1556 PetscErrorCode ierr; 1557 PetscInt ma,na,mb,nb, i; 1558 1559 PetscFunctionBegin; 1560 bij = (Mat_SeqAIJ *) B->data; 1561 1562 ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr); 1563 ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr); 1564 if (ma!=nb || na!=mb){ 1565 *f = PETSC_FALSE; 1566 PetscFunctionReturn(0); 1567 } 1568 aii = aij->i; bii = bij->i; 1569 adx = aij->j; bdx = bij->j; 1570 va = aij->a; vb = bij->a; 1571 ierr = PetscMalloc(ma*sizeof(PetscInt),&aptr);CHKERRQ(ierr); 1572 ierr = PetscMalloc(mb*sizeof(PetscInt),&bptr);CHKERRQ(ierr); 1573 for (i=0; i<ma; i++) aptr[i] = aii[i]; 1574 for (i=0; i<mb; i++) bptr[i] = bii[i]; 1575 1576 *f = PETSC_TRUE; 1577 for (i=0; i<ma; i++) { 1578 while (aptr[i]<aii[i+1]) { 1579 PetscInt idc,idr; 1580 PetscScalar vc,vr; 1581 /* column/row index/value */ 1582 idc = adx[aptr[i]]; 1583 idr = bdx[bptr[idc]]; 1584 vc = va[aptr[i]]; 1585 vr = vb[bptr[idc]]; 1586 if (i!=idr || PetscAbsScalar(vc-vr) > tol) { 1587 *f = PETSC_FALSE; 1588 goto done; 1589 } else { 1590 aptr[i]++; 1591 if (B || i!=idc) bptr[idc]++; 1592 } 1593 } 1594 } 1595 done: 1596 ierr = PetscFree(aptr);CHKERRQ(ierr); 1597 if (B) { 1598 ierr = PetscFree(bptr);CHKERRQ(ierr); 1599 } 1600 PetscFunctionReturn(0); 1601 } 1602 EXTERN_C_END 1603 1604 EXTERN_C_BEGIN 1605 #undef __FUNCT__ 1606 #define __FUNCT__ "MatIsHermitianTranspose_SeqAIJ" 1607 PetscErrorCode PETSCMAT_DLLEXPORT MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscTruth *f) 1608 { 1609 Mat_SeqAIJ *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data; 1610 PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr; 1611 MatScalar *va,*vb; 1612 PetscErrorCode ierr; 1613 PetscInt ma,na,mb,nb, i; 1614 1615 PetscFunctionBegin; 1616 bij = (Mat_SeqAIJ *) B->data; 1617 1618 ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr); 1619 ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr); 1620 if (ma!=nb || na!=mb){ 1621 *f = PETSC_FALSE; 1622 PetscFunctionReturn(0); 1623 } 1624 aii = aij->i; bii = bij->i; 1625 adx = aij->j; bdx = bij->j; 1626 va = aij->a; vb = bij->a; 1627 ierr = PetscMalloc(ma*sizeof(PetscInt),&aptr);CHKERRQ(ierr); 1628 ierr = PetscMalloc(mb*sizeof(PetscInt),&bptr);CHKERRQ(ierr); 1629 for (i=0; i<ma; i++) aptr[i] = aii[i]; 1630 for (i=0; i<mb; i++) bptr[i] = bii[i]; 1631 1632 *f = PETSC_TRUE; 1633 for (i=0; i<ma; i++) { 1634 while (aptr[i]<aii[i+1]) { 1635 PetscInt idc,idr; 1636 PetscScalar vc,vr; 1637 /* column/row index/value */ 1638 idc = adx[aptr[i]]; 1639 idr = bdx[bptr[idc]]; 1640 vc = va[aptr[i]]; 1641 vr = vb[bptr[idc]]; 1642 if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) { 1643 *f = PETSC_FALSE; 1644 goto done; 1645 } else { 1646 aptr[i]++; 1647 if (B || i!=idc) bptr[idc]++; 1648 } 1649 } 1650 } 1651 done: 1652 ierr = PetscFree(aptr);CHKERRQ(ierr); 1653 if (B) { 1654 ierr = PetscFree(bptr);CHKERRQ(ierr); 1655 } 1656 PetscFunctionReturn(0); 1657 } 1658 EXTERN_C_END 1659 1660 #undef __FUNCT__ 1661 #define __FUNCT__ "MatIsSymmetric_SeqAIJ" 1662 PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscTruth *f) 1663 { 1664 PetscErrorCode ierr; 1665 PetscFunctionBegin; 1666 ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr); 1667 PetscFunctionReturn(0); 1668 } 1669 1670 #undef __FUNCT__ 1671 #define __FUNCT__ "MatIsHermitian_SeqAIJ" 1672 PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscTruth *f) 1673 { 1674 PetscErrorCode ierr; 1675 PetscFunctionBegin; 1676 ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr); 1677 PetscFunctionReturn(0); 1678 } 1679 1680 #undef __FUNCT__ 1681 #define __FUNCT__ "MatDiagonalScale_SeqAIJ" 1682 PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr) 1683 { 1684 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1685 PetscScalar *l,*r,x; 1686 MatScalar *v; 1687 PetscErrorCode ierr; 1688 PetscInt i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz,*jj; 1689 1690 PetscFunctionBegin; 1691 if (ll) { 1692 /* The local size is used so that VecMPI can be passed to this routine 1693 by MatDiagonalScale_MPIAIJ */ 1694 ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr); 1695 if (m != A->rmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length"); 1696 ierr = VecGetArray(ll,&l);CHKERRQ(ierr); 1697 v = a->a; 1698 for (i=0; i<m; i++) { 1699 x = l[i]; 1700 M = a->i[i+1] - a->i[i]; 1701 for (j=0; j<M; j++) { (*v++) *= x;} 1702 } 1703 ierr = VecRestoreArray(ll,&l);CHKERRQ(ierr); 1704 ierr = PetscLogFlops(nz);CHKERRQ(ierr); 1705 } 1706 if (rr) { 1707 ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr); 1708 if (n != A->cmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length"); 1709 ierr = VecGetArray(rr,&r);CHKERRQ(ierr); 1710 v = a->a; jj = a->j; 1711 for (i=0; i<nz; i++) { 1712 (*v++) *= r[*jj++]; 1713 } 1714 ierr = VecRestoreArray(rr,&r);CHKERRQ(ierr); 1715 ierr = PetscLogFlops(nz);CHKERRQ(ierr); 1716 } 1717 PetscFunctionReturn(0); 1718 } 1719 1720 #undef __FUNCT__ 1721 #define __FUNCT__ "MatGetSubMatrix_SeqAIJ" 1722 PetscErrorCode MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B) 1723 { 1724 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*c; 1725 PetscErrorCode ierr; 1726 PetscInt *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens; 1727 PetscInt row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi; 1728 const PetscInt *irow,*icol; 1729 PetscInt nrows,ncols; 1730 PetscInt *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen; 1731 MatScalar *a_new,*mat_a; 1732 Mat C; 1733 PetscTruth stride,sorted; 1734 1735 PetscFunctionBegin; 1736 ierr = ISSorted(isrow,&sorted);CHKERRQ(ierr); 1737 if (!sorted) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"ISrow is not sorted"); 1738 ierr = ISSorted(iscol,&sorted);CHKERRQ(ierr); 1739 if (!sorted) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"IScol is not sorted"); 1740 1741 ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr); 1742 ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr); 1743 ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr); 1744 1745 ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr); 1746 ierr = ISStride(iscol,&stride);CHKERRQ(ierr); 1747 if (stride && step == 1) { 1748 /* special case of contiguous rows */ 1749 ierr = PetscMalloc2(nrows,PetscInt,&lens,nrows,PetscInt,&starts);CHKERRQ(ierr); 1750 /* loop over new rows determining lens and starting points */ 1751 for (i=0; i<nrows; i++) { 1752 kstart = ai[irow[i]]; 1753 kend = kstart + ailen[irow[i]]; 1754 for (k=kstart; k<kend; k++) { 1755 if (aj[k] >= first) { 1756 starts[i] = k; 1757 break; 1758 } 1759 } 1760 sum = 0; 1761 while (k < kend) { 1762 if (aj[k++] >= first+ncols) break; 1763 sum++; 1764 } 1765 lens[i] = sum; 1766 } 1767 /* create submatrix */ 1768 if (scall == MAT_REUSE_MATRIX) { 1769 PetscInt n_cols,n_rows; 1770 ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr); 1771 if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size"); 1772 ierr = MatZeroEntries(*B);CHKERRQ(ierr); 1773 C = *B; 1774 } else { 1775 ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr); 1776 ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 1777 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 1778 ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr); 1779 } 1780 c = (Mat_SeqAIJ*)C->data; 1781 1782 /* loop over rows inserting into submatrix */ 1783 a_new = c->a; 1784 j_new = c->j; 1785 i_new = c->i; 1786 1787 for (i=0; i<nrows; i++) { 1788 ii = starts[i]; 1789 lensi = lens[i]; 1790 for (k=0; k<lensi; k++) { 1791 *j_new++ = aj[ii+k] - first; 1792 } 1793 ierr = PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(PetscScalar));CHKERRQ(ierr); 1794 a_new += lensi; 1795 i_new[i+1] = i_new[i] + lensi; 1796 c->ilen[i] = lensi; 1797 } 1798 ierr = PetscFree2(lens,starts);CHKERRQ(ierr); 1799 } else { 1800 ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr); 1801 ierr = PetscMalloc(oldcols*sizeof(PetscInt),&smap);CHKERRQ(ierr); 1802 ierr = PetscMemzero(smap,oldcols*sizeof(PetscInt));CHKERRQ(ierr); 1803 ierr = PetscMalloc((1+nrows)*sizeof(PetscInt),&lens);CHKERRQ(ierr); 1804 for (i=0; i<ncols; i++) smap[icol[i]] = i+1; 1805 /* determine lens of each row */ 1806 for (i=0; i<nrows; i++) { 1807 kstart = ai[irow[i]]; 1808 kend = kstart + a->ilen[irow[i]]; 1809 lens[i] = 0; 1810 for (k=kstart; k<kend; k++) { 1811 if (smap[aj[k]]) { 1812 lens[i]++; 1813 } 1814 } 1815 } 1816 /* Create and fill new matrix */ 1817 if (scall == MAT_REUSE_MATRIX) { 1818 PetscTruth equal; 1819 1820 c = (Mat_SeqAIJ *)((*B)->data); 1821 if ((*B)->rmap->n != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size"); 1822 ierr = PetscMemcmp(c->ilen,lens,(*B)->rmap->n*sizeof(PetscInt),&equal);CHKERRQ(ierr); 1823 if (!equal) { 1824 SETERRQ(PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros"); 1825 } 1826 ierr = PetscMemzero(c->ilen,(*B)->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 1827 C = *B; 1828 } else { 1829 ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr); 1830 ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 1831 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 1832 ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr); 1833 } 1834 c = (Mat_SeqAIJ *)(C->data); 1835 for (i=0; i<nrows; i++) { 1836 row = irow[i]; 1837 kstart = ai[row]; 1838 kend = kstart + a->ilen[row]; 1839 mat_i = c->i[i]; 1840 mat_j = c->j + mat_i; 1841 mat_a = c->a + mat_i; 1842 mat_ilen = c->ilen + i; 1843 for (k=kstart; k<kend; k++) { 1844 if ((tcol=smap[a->j[k]])) { 1845 *mat_j++ = tcol - 1; 1846 *mat_a++ = a->a[k]; 1847 (*mat_ilen)++; 1848 1849 } 1850 } 1851 } 1852 /* Free work space */ 1853 ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr); 1854 ierr = PetscFree(smap);CHKERRQ(ierr); 1855 ierr = PetscFree(lens);CHKERRQ(ierr); 1856 } 1857 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1858 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1859 1860 ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr); 1861 *B = C; 1862 PetscFunctionReturn(0); 1863 } 1864 1865 #undef __FUNCT__ 1866 #define __FUNCT__ "MatILUFactor_SeqAIJ_newdatastruct" 1867 PetscErrorCode MatILUFactor_SeqAIJ_newdatastruct(Mat inA,IS row,IS col,const MatFactorInfo *info) 1868 { 1869 PetscErrorCode ierr; 1870 Mat C; 1871 1872 PetscFunctionBegin; 1873 /* A new factored matrix C replaces original matrix inA, not a truely in-place ILUFactor yet */ 1874 ierr = MatGetFactor(inA,MAT_SOLVER_PETSC,MAT_FACTOR_LU,&C);CHKERRQ(ierr); 1875 ierr = MatILUFactorSymbolic_SeqAIJ_newdatastruct(C,inA,row,col,info);CHKERRQ(ierr); 1876 ierr = MatLUFactorNumeric_SeqAIJ_newdatastruct(C,inA,info);CHKERRQ(ierr); 1877 inA->ops->solve = C->ops->solve; 1878 inA->ops->solvetranspose = C->ops->solvetranspose; 1879 ierr = MatHeaderCopy(inA,C);CHKERRQ(ierr); 1880 ierr = PetscLogObjectParent(inA,((Mat_SeqAIJ*)(inA->data))->icol);CHKERRQ(ierr); 1881 PetscFunctionReturn(0); 1882 } 1883 1884 #undef __FUNCT__ 1885 #define __FUNCT__ "MatILUFactor_SeqAIJ" 1886 PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info) 1887 { 1888 Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 1889 PetscErrorCode ierr; 1890 Mat outA; 1891 PetscTruth row_identity,col_identity; 1892 PetscTruth newdatastruct=PETSC_FALSE; 1893 1894 PetscFunctionBegin; 1895 ierr = PetscOptionsGetTruth(PETSC_NULL,"-ilu_new",&newdatastruct,PETSC_NULL);CHKERRQ(ierr); 1896 if(newdatastruct){ 1897 ierr = MatILUFactor_SeqAIJ_newdatastruct(inA,row,col,info);CHKERRQ(ierr); 1898 PetscFunctionReturn(0); 1899 } 1900 1901 if (info->levels != 0) SETERRQ(PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu"); 1902 1903 ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr); 1904 ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr); 1905 1906 outA = inA; 1907 outA->factor = MAT_FACTOR_LU; 1908 ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr); 1909 if (a->row) { ierr = ISDestroy(a->row);CHKERRQ(ierr);} 1910 a->row = row; 1911 ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr); 1912 if (a->col) { ierr = ISDestroy(a->col);CHKERRQ(ierr);} 1913 a->col = col; 1914 1915 /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */ 1916 if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);} /* need to remove old one */ 1917 ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr); 1918 ierr = PetscLogObjectParent(inA,a->icol);CHKERRQ(ierr); 1919 1920 if (!a->solve_work) { /* this matrix may have been factored before */ 1921 ierr = PetscMalloc((inA->rmap->n+1)*sizeof(PetscScalar),&a->solve_work);CHKERRQ(ierr); 1922 ierr = PetscLogObjectMemory(inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr); 1923 } 1924 1925 ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr); 1926 if (row_identity && col_identity) { 1927 ierr = MatLUFactorNumeric_SeqAIJ(outA,inA,info);CHKERRQ(ierr); 1928 } else { 1929 ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr); 1930 } 1931 PetscFunctionReturn(0); 1932 } 1933 1934 #include "petscblaslapack.h" 1935 #undef __FUNCT__ 1936 #define __FUNCT__ "MatScale_SeqAIJ" 1937 PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha) 1938 { 1939 Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 1940 PetscScalar oalpha = alpha; 1941 PetscErrorCode ierr; 1942 PetscBLASInt one = 1,bnz = PetscBLASIntCast(a->nz); 1943 1944 PetscFunctionBegin; 1945 BLASscal_(&bnz,&oalpha,a->a,&one); 1946 ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); 1947 PetscFunctionReturn(0); 1948 } 1949 1950 #undef __FUNCT__ 1951 #define __FUNCT__ "MatGetSubMatrices_SeqAIJ" 1952 PetscErrorCode MatGetSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[]) 1953 { 1954 PetscErrorCode ierr; 1955 PetscInt i; 1956 1957 PetscFunctionBegin; 1958 if (scall == MAT_INITIAL_MATRIX) { 1959 ierr = PetscMalloc((n+1)*sizeof(Mat),B);CHKERRQ(ierr); 1960 } 1961 1962 for (i=0; i<n; i++) { 1963 ierr = MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr); 1964 } 1965 PetscFunctionReturn(0); 1966 } 1967 1968 #undef __FUNCT__ 1969 #define __FUNCT__ "MatIncreaseOverlap_SeqAIJ" 1970 PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov) 1971 { 1972 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1973 PetscErrorCode ierr; 1974 PetscInt row,i,j,k,l,m,n,*nidx,isz,val; 1975 const PetscInt *idx; 1976 PetscInt start,end,*ai,*aj; 1977 PetscBT table; 1978 1979 PetscFunctionBegin; 1980 m = A->rmap->n; 1981 ai = a->i; 1982 aj = a->j; 1983 1984 if (ov < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used"); 1985 1986 ierr = PetscMalloc((m+1)*sizeof(PetscInt),&nidx);CHKERRQ(ierr); 1987 ierr = PetscBTCreate(m,table);CHKERRQ(ierr); 1988 1989 for (i=0; i<is_max; i++) { 1990 /* Initialize the two local arrays */ 1991 isz = 0; 1992 ierr = PetscBTMemzero(m,table);CHKERRQ(ierr); 1993 1994 /* Extract the indices, assume there can be duplicate entries */ 1995 ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr); 1996 ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr); 1997 1998 /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 1999 for (j=0; j<n ; ++j){ 2000 if(!PetscBTLookupSet(table,idx[j])) { nidx[isz++] = idx[j];} 2001 } 2002 ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr); 2003 ierr = ISDestroy(is[i]);CHKERRQ(ierr); 2004 2005 k = 0; 2006 for (j=0; j<ov; j++){ /* for each overlap */ 2007 n = isz; 2008 for (; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */ 2009 row = nidx[k]; 2010 start = ai[row]; 2011 end = ai[row+1]; 2012 for (l = start; l<end ; l++){ 2013 val = aj[l] ; 2014 if (!PetscBTLookupSet(table,val)) {nidx[isz++] = val;} 2015 } 2016 } 2017 } 2018 ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,(is+i));CHKERRQ(ierr); 2019 } 2020 ierr = PetscBTDestroy(table);CHKERRQ(ierr); 2021 ierr = PetscFree(nidx);CHKERRQ(ierr); 2022 PetscFunctionReturn(0); 2023 } 2024 2025 /* -------------------------------------------------------------- */ 2026 #undef __FUNCT__ 2027 #define __FUNCT__ "MatPermute_SeqAIJ" 2028 PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B) 2029 { 2030 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2031 PetscErrorCode ierr; 2032 PetscInt i,nz,m = A->rmap->n,n = A->cmap->n; 2033 const PetscInt *row,*col; 2034 PetscInt *cnew,j,*lens; 2035 IS icolp,irowp; 2036 PetscInt *cwork; 2037 PetscScalar *vwork; 2038 2039 PetscFunctionBegin; 2040 ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr); 2041 ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr); 2042 ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr); 2043 ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr); 2044 2045 /* determine lengths of permuted rows */ 2046 ierr = PetscMalloc((m+1)*sizeof(PetscInt),&lens);CHKERRQ(ierr); 2047 for (i=0; i<m; i++) { 2048 lens[row[i]] = a->i[i+1] - a->i[i]; 2049 } 2050 ierr = MatCreate(((PetscObject)A)->comm,B);CHKERRQ(ierr); 2051 ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr); 2052 ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr); 2053 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr); 2054 ierr = PetscFree(lens);CHKERRQ(ierr); 2055 2056 ierr = PetscMalloc(n*sizeof(PetscInt),&cnew);CHKERRQ(ierr); 2057 for (i=0; i<m; i++) { 2058 ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr); 2059 for (j=0; j<nz; j++) { cnew[j] = col[cwork[j]];} 2060 ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr); 2061 ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr); 2062 } 2063 ierr = PetscFree(cnew);CHKERRQ(ierr); 2064 (*B)->assembled = PETSC_FALSE; 2065 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2066 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2067 ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr); 2068 ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr); 2069 ierr = ISDestroy(irowp);CHKERRQ(ierr); 2070 ierr = ISDestroy(icolp);CHKERRQ(ierr); 2071 PetscFunctionReturn(0); 2072 } 2073 2074 #undef __FUNCT__ 2075 #define __FUNCT__ "MatCopy_SeqAIJ" 2076 PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str) 2077 { 2078 PetscErrorCode ierr; 2079 2080 PetscFunctionBegin; 2081 /* If the two matrices have the same copy implementation, use fast copy. */ 2082 if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) { 2083 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2084 Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 2085 2086 if (a->i[A->rmap->n] != b->i[B->rmap->n]) { 2087 SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different"); 2088 } 2089 ierr = PetscMemcpy(b->a,a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));CHKERRQ(ierr); 2090 } else { 2091 ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr); 2092 } 2093 PetscFunctionReturn(0); 2094 } 2095 2096 #undef __FUNCT__ 2097 #define __FUNCT__ "MatSetUpPreallocation_SeqAIJ" 2098 PetscErrorCode MatSetUpPreallocation_SeqAIJ(Mat A) 2099 { 2100 PetscErrorCode ierr; 2101 2102 PetscFunctionBegin; 2103 ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,0);CHKERRQ(ierr); 2104 PetscFunctionReturn(0); 2105 } 2106 2107 #undef __FUNCT__ 2108 #define __FUNCT__ "MatGetArray_SeqAIJ" 2109 PetscErrorCode MatGetArray_SeqAIJ(Mat A,PetscScalar *array[]) 2110 { 2111 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2112 PetscFunctionBegin; 2113 *array = a->a; 2114 PetscFunctionReturn(0); 2115 } 2116 2117 #undef __FUNCT__ 2118 #define __FUNCT__ "MatRestoreArray_SeqAIJ" 2119 PetscErrorCode MatRestoreArray_SeqAIJ(Mat A,PetscScalar *array[]) 2120 { 2121 PetscFunctionBegin; 2122 PetscFunctionReturn(0); 2123 } 2124 2125 #undef __FUNCT__ 2126 #define __FUNCT__ "MatFDColoringApply_SeqAIJ" 2127 PetscErrorCode MatFDColoringApply_SeqAIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx) 2128 { 2129 PetscErrorCode (*f)(void*,Vec,Vec,void*) = (PetscErrorCode (*)(void*,Vec,Vec,void *))coloring->f; 2130 PetscErrorCode ierr; 2131 PetscInt k,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2; 2132 PetscScalar dx,*y,*xx,*w3_array; 2133 PetscScalar *vscale_array; 2134 PetscReal epsilon = coloring->error_rel,umin = coloring->umin; 2135 Vec w1,w2,w3; 2136 void *fctx = coloring->fctx; 2137 PetscTruth flg = PETSC_FALSE; 2138 2139 PetscFunctionBegin; 2140 if (!coloring->w1) { 2141 ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr); 2142 ierr = PetscLogObjectParent(coloring,coloring->w1);CHKERRQ(ierr); 2143 ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr); 2144 ierr = PetscLogObjectParent(coloring,coloring->w2);CHKERRQ(ierr); 2145 ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr); 2146 ierr = PetscLogObjectParent(coloring,coloring->w3);CHKERRQ(ierr); 2147 } 2148 w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3; 2149 2150 ierr = MatSetUnfactored(J);CHKERRQ(ierr); 2151 ierr = PetscOptionsGetTruth(((PetscObject)coloring)->prefix,"-mat_fd_coloring_dont_rezero",&flg,PETSC_NULL);CHKERRQ(ierr); 2152 if (flg) { 2153 ierr = PetscInfo(coloring,"Not calling MatZeroEntries()\n");CHKERRQ(ierr); 2154 } else { 2155 PetscTruth assembled; 2156 ierr = MatAssembled(J,&assembled);CHKERRQ(ierr); 2157 if (assembled) { 2158 ierr = MatZeroEntries(J);CHKERRQ(ierr); 2159 } 2160 } 2161 2162 ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr); 2163 ierr = VecGetSize(x1,&N);CHKERRQ(ierr); 2164 2165 /* 2166 This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets 2167 coloring->F for the coarser grids from the finest 2168 */ 2169 if (coloring->F) { 2170 ierr = VecGetLocalSize(coloring->F,&m1);CHKERRQ(ierr); 2171 ierr = VecGetLocalSize(w1,&m2);CHKERRQ(ierr); 2172 if (m1 != m2) { 2173 coloring->F = 0; 2174 } 2175 } 2176 2177 if (coloring->F) { 2178 w1 = coloring->F; 2179 coloring->F = 0; 2180 } else { 2181 ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 2182 ierr = (*f)(sctx,x1,w1,fctx);CHKERRQ(ierr); 2183 ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 2184 } 2185 2186 /* 2187 Compute all the scale factors and share with other processors 2188 */ 2189 ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start; 2190 ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start; 2191 for (k=0; k<coloring->ncolors; k++) { 2192 /* 2193 Loop over each column associated with color adding the 2194 perturbation to the vector w3. 2195 */ 2196 for (l=0; l<coloring->ncolumns[k]; l++) { 2197 col = coloring->columns[k][l]; /* column of the matrix we are probing for */ 2198 dx = xx[col]; 2199 if (dx == 0.0) dx = 1.0; 2200 #if !defined(PETSC_USE_COMPLEX) 2201 if (dx < umin && dx >= 0.0) dx = umin; 2202 else if (dx < 0.0 && dx > -umin) dx = -umin; 2203 #else 2204 if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin; 2205 else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin; 2206 #endif 2207 dx *= epsilon; 2208 vscale_array[col] = 1.0/dx; 2209 } 2210 } 2211 vscale_array = vscale_array + start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 2212 ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2213 ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2214 2215 /* ierr = VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD); 2216 ierr = VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/ 2217 2218 if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow; 2219 else vscaleforrow = coloring->columnsforrow; 2220 2221 ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 2222 /* 2223 Loop over each color 2224 */ 2225 for (k=0; k<coloring->ncolors; k++) { 2226 coloring->currentcolor = k; 2227 ierr = VecCopy(x1,w3);CHKERRQ(ierr); 2228 ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start; 2229 /* 2230 Loop over each column associated with color adding the 2231 perturbation to the vector w3. 2232 */ 2233 for (l=0; l<coloring->ncolumns[k]; l++) { 2234 col = coloring->columns[k][l]; /* column of the matrix we are probing for */ 2235 dx = xx[col]; 2236 if (dx == 0.0) dx = 1.0; 2237 #if !defined(PETSC_USE_COMPLEX) 2238 if (dx < umin && dx >= 0.0) dx = umin; 2239 else if (dx < 0.0 && dx > -umin) dx = -umin; 2240 #else 2241 if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin; 2242 else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin; 2243 #endif 2244 dx *= epsilon; 2245 if (!PetscAbsScalar(dx)) SETERRQ(PETSC_ERR_PLIB,"Computed 0 differencing parameter"); 2246 w3_array[col] += dx; 2247 } 2248 w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr); 2249 2250 /* 2251 Evaluate function at x1 + dx (here dx is a vector of perturbations) 2252 */ 2253 2254 ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 2255 ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr); 2256 ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 2257 ierr = VecAXPY(w2,-1.0,w1);CHKERRQ(ierr); 2258 2259 /* 2260 Loop over rows of vector, putting results into Jacobian matrix 2261 */ 2262 ierr = VecGetArray(w2,&y);CHKERRQ(ierr); 2263 for (l=0; l<coloring->nrows[k]; l++) { 2264 row = coloring->rows[k][l]; 2265 col = coloring->columnsforrow[k][l]; 2266 y[row] *= vscale_array[vscaleforrow[k][l]]; 2267 srow = row + start; 2268 ierr = MatSetValues_SeqAIJ(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr); 2269 } 2270 ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr); 2271 } 2272 coloring->currentcolor = k; 2273 ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 2274 xx = xx + start; ierr = VecRestoreArray(x1,&xx);CHKERRQ(ierr); 2275 ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2276 ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2277 PetscFunctionReturn(0); 2278 } 2279 2280 #include "petscblaslapack.h" 2281 #undef __FUNCT__ 2282 #define __FUNCT__ "MatAXPY_SeqAIJ" 2283 PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str) 2284 { 2285 PetscErrorCode ierr; 2286 PetscInt i; 2287 Mat_SeqAIJ *x = (Mat_SeqAIJ *)X->data,*y = (Mat_SeqAIJ *)Y->data; 2288 PetscBLASInt one=1,bnz = PetscBLASIntCast(x->nz); 2289 2290 PetscFunctionBegin; 2291 if (str == SAME_NONZERO_PATTERN) { 2292 PetscScalar alpha = a; 2293 BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one); 2294 } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 2295 if (y->xtoy && y->XtoY != X) { 2296 ierr = PetscFree(y->xtoy);CHKERRQ(ierr); 2297 ierr = MatDestroy(y->XtoY);CHKERRQ(ierr); 2298 } 2299 if (!y->xtoy) { /* get xtoy */ 2300 ierr = MatAXPYGetxtoy_Private(X->rmap->n,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);CHKERRQ(ierr); 2301 y->XtoY = X; 2302 ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 2303 } 2304 for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += a*(x->a[i]); 2305 ierr = PetscInfo3(Y,"ratio of nnz(X)/nnz(Y): %d/%d = %G\n",x->nz,y->nz,(PetscReal)(x->nz)/y->nz);CHKERRQ(ierr); 2306 } else { 2307 ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr); 2308 } 2309 PetscFunctionReturn(0); 2310 } 2311 2312 #undef __FUNCT__ 2313 #define __FUNCT__ "MatSetBlockSize_SeqAIJ" 2314 PetscErrorCode MatSetBlockSize_SeqAIJ(Mat A,PetscInt bs) 2315 { 2316 PetscErrorCode ierr; 2317 2318 PetscFunctionBegin; 2319 ierr = PetscLayoutSetBlockSize(A->rmap,bs);CHKERRQ(ierr); 2320 ierr = PetscLayoutSetBlockSize(A->cmap,bs);CHKERRQ(ierr); 2321 PetscFunctionReturn(0); 2322 } 2323 2324 #undef __FUNCT__ 2325 #define __FUNCT__ "MatConjugate_SeqAIJ" 2326 PetscErrorCode PETSCMAT_DLLEXPORT MatConjugate_SeqAIJ(Mat mat) 2327 { 2328 #if defined(PETSC_USE_COMPLEX) 2329 Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2330 PetscInt i,nz; 2331 PetscScalar *a; 2332 2333 PetscFunctionBegin; 2334 nz = aij->nz; 2335 a = aij->a; 2336 for (i=0; i<nz; i++) { 2337 a[i] = PetscConj(a[i]); 2338 } 2339 #else 2340 PetscFunctionBegin; 2341 #endif 2342 PetscFunctionReturn(0); 2343 } 2344 2345 #undef __FUNCT__ 2346 #define __FUNCT__ "MatGetRowMaxAbs_SeqAIJ" 2347 PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2348 { 2349 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2350 PetscErrorCode ierr; 2351 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2352 PetscReal atmp; 2353 PetscScalar *x; 2354 MatScalar *aa; 2355 2356 PetscFunctionBegin; 2357 if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2358 aa = a->a; 2359 ai = a->i; 2360 aj = a->j; 2361 2362 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2363 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2364 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 2365 if (n != A->rmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2366 for (i=0; i<m; i++) { 2367 ncols = ai[1] - ai[0]; ai++; 2368 x[i] = 0.0; 2369 for (j=0; j<ncols; j++){ 2370 atmp = PetscAbsScalar(*aa); 2371 if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;} 2372 aa++; aj++; 2373 } 2374 } 2375 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2376 PetscFunctionReturn(0); 2377 } 2378 2379 #undef __FUNCT__ 2380 #define __FUNCT__ "MatGetRowMax_SeqAIJ" 2381 PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2382 { 2383 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2384 PetscErrorCode ierr; 2385 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2386 PetscScalar *x; 2387 MatScalar *aa; 2388 2389 PetscFunctionBegin; 2390 if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2391 aa = a->a; 2392 ai = a->i; 2393 aj = a->j; 2394 2395 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2396 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2397 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 2398 if (n != A->rmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2399 for (i=0; i<m; i++) { 2400 ncols = ai[1] - ai[0]; ai++; 2401 if (ncols == A->cmap->n) { /* row is dense */ 2402 x[i] = *aa; if (idx) idx[i] = 0; 2403 } else { /* row is sparse so already KNOW maximum is 0.0 or higher */ 2404 x[i] = 0.0; 2405 if (idx) { 2406 idx[i] = 0; /* in case ncols is zero */ 2407 for (j=0;j<ncols;j++) { /* find first implicit 0.0 in the row */ 2408 if (aj[j] > j) { 2409 idx[i] = j; 2410 break; 2411 } 2412 } 2413 } 2414 } 2415 for (j=0; j<ncols; j++){ 2416 if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 2417 aa++; aj++; 2418 } 2419 } 2420 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2421 PetscFunctionReturn(0); 2422 } 2423 2424 #undef __FUNCT__ 2425 #define __FUNCT__ "MatGetRowMinAbs_SeqAIJ" 2426 PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2427 { 2428 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2429 PetscErrorCode ierr; 2430 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2431 PetscReal atmp; 2432 PetscScalar *x; 2433 MatScalar *aa; 2434 2435 PetscFunctionBegin; 2436 if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2437 aa = a->a; 2438 ai = a->i; 2439 aj = a->j; 2440 2441 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2442 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2443 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 2444 if (n != A->rmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2445 for (i=0; i<m; i++) { 2446 ncols = ai[1] - ai[0]; ai++; 2447 if (ncols) { 2448 /* Get first nonzero */ 2449 for(j = 0; j < ncols; j++) { 2450 atmp = PetscAbsScalar(aa[j]); 2451 if (atmp > 1.0e-12) {x[i] = atmp; if (idx) idx[i] = aj[j]; break;} 2452 } 2453 if (j == ncols) {x[i] = *aa; if (idx) idx[i] = *aj;} 2454 } else { 2455 x[i] = 0.0; if (idx) idx[i] = 0; 2456 } 2457 for(j = 0; j < ncols; j++) { 2458 atmp = PetscAbsScalar(*aa); 2459 if (atmp > 1.0e-12 && PetscAbsScalar(x[i]) > atmp) {x[i] = atmp; if (idx) idx[i] = *aj;} 2460 aa++; aj++; 2461 } 2462 } 2463 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2464 PetscFunctionReturn(0); 2465 } 2466 2467 #undef __FUNCT__ 2468 #define __FUNCT__ "MatGetRowMin_SeqAIJ" 2469 PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 2470 { 2471 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2472 PetscErrorCode ierr; 2473 PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 2474 PetscScalar *x; 2475 MatScalar *aa; 2476 2477 PetscFunctionBegin; 2478 if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2479 aa = a->a; 2480 ai = a->i; 2481 aj = a->j; 2482 2483 ierr = VecSet(v,0.0);CHKERRQ(ierr); 2484 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 2485 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 2486 if (n != A->rmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 2487 for (i=0; i<m; i++) { 2488 ncols = ai[1] - ai[0]; ai++; 2489 if (ncols == A->cmap->n) { /* row is dense */ 2490 x[i] = *aa; if (idx) idx[i] = 0; 2491 } else { /* row is sparse so already KNOW minimum is 0.0 or lower */ 2492 x[i] = 0.0; 2493 if (idx) { /* find first implicit 0.0 in the row */ 2494 idx[i] = 0; /* in case ncols is zero */ 2495 for (j=0;j<ncols;j++) { 2496 if (aj[j] > j) { 2497 idx[i] = j; 2498 break; 2499 } 2500 } 2501 } 2502 } 2503 for (j=0; j<ncols; j++){ 2504 if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 2505 aa++; aj++; 2506 } 2507 } 2508 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 2509 PetscFunctionReturn(0); 2510 } 2511 extern PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringApply_AIJ(Mat,MatFDColoring,Vec,MatStructure*,void*); 2512 /* -------------------------------------------------------------------*/ 2513 static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ, 2514 MatGetRow_SeqAIJ, 2515 MatRestoreRow_SeqAIJ, 2516 MatMult_SeqAIJ, 2517 /* 4*/ MatMultAdd_SeqAIJ, 2518 MatMultTranspose_SeqAIJ, 2519 MatMultTransposeAdd_SeqAIJ, 2520 0, 2521 0, 2522 0, 2523 /*10*/ 0, 2524 MatLUFactor_SeqAIJ, 2525 0, 2526 MatSOR_SeqAIJ, 2527 MatTranspose_SeqAIJ, 2528 /*15*/ MatGetInfo_SeqAIJ, 2529 MatEqual_SeqAIJ, 2530 MatGetDiagonal_SeqAIJ, 2531 MatDiagonalScale_SeqAIJ, 2532 MatNorm_SeqAIJ, 2533 /*20*/ 0, 2534 MatAssemblyEnd_SeqAIJ, 2535 MatSetOption_SeqAIJ, 2536 MatZeroEntries_SeqAIJ, 2537 /*24*/ MatZeroRows_SeqAIJ, 2538 0, 2539 0, 2540 0, 2541 0, 2542 /*29*/ MatSetUpPreallocation_SeqAIJ, 2543 0, 2544 0, 2545 MatGetArray_SeqAIJ, 2546 MatRestoreArray_SeqAIJ, 2547 /*34*/ MatDuplicate_SeqAIJ, 2548 0, 2549 0, 2550 MatILUFactor_SeqAIJ, 2551 0, 2552 /*39*/ MatAXPY_SeqAIJ, 2553 MatGetSubMatrices_SeqAIJ, 2554 MatIncreaseOverlap_SeqAIJ, 2555 MatGetValues_SeqAIJ, 2556 MatCopy_SeqAIJ, 2557 /*44*/ MatGetRowMax_SeqAIJ, 2558 MatScale_SeqAIJ, 2559 0, 2560 MatDiagonalSet_SeqAIJ, 2561 MatILUDTFactor_SeqAIJ, 2562 /*49*/ MatSetBlockSize_SeqAIJ, 2563 MatGetRowIJ_SeqAIJ, 2564 MatRestoreRowIJ_SeqAIJ, 2565 MatGetColumnIJ_SeqAIJ, 2566 MatRestoreColumnIJ_SeqAIJ, 2567 /*54*/ MatFDColoringCreate_SeqAIJ, 2568 0, 2569 0, 2570 MatPermute_SeqAIJ, 2571 0, 2572 /*59*/ 0, 2573 MatDestroy_SeqAIJ, 2574 MatView_SeqAIJ, 2575 0, 2576 0, 2577 /*64*/ 0, 2578 0, 2579 0, 2580 0, 2581 0, 2582 /*69*/ MatGetRowMaxAbs_SeqAIJ, 2583 MatGetRowMinAbs_SeqAIJ, 2584 0, 2585 MatSetColoring_SeqAIJ, 2586 #if defined(PETSC_HAVE_ADIC) 2587 MatSetValuesAdic_SeqAIJ, 2588 #else 2589 0, 2590 #endif 2591 /*74*/ MatSetValuesAdifor_SeqAIJ, 2592 MatFDColoringApply_AIJ, 2593 0, 2594 0, 2595 0, 2596 /*79*/ 0, 2597 0, 2598 0, 2599 0, 2600 MatLoad_SeqAIJ, 2601 /*84*/ MatIsSymmetric_SeqAIJ, 2602 MatIsHermitian_SeqAIJ, 2603 0, 2604 0, 2605 0, 2606 /*89*/ MatMatMult_SeqAIJ_SeqAIJ, 2607 MatMatMultSymbolic_SeqAIJ_SeqAIJ, 2608 MatMatMultNumeric_SeqAIJ_SeqAIJ, 2609 MatPtAP_Basic, 2610 MatPtAPSymbolic_SeqAIJ, 2611 /*94*/ MatPtAPNumeric_SeqAIJ, 2612 MatMatMultTranspose_SeqAIJ_SeqAIJ, 2613 MatMatMultTransposeSymbolic_SeqAIJ_SeqAIJ, 2614 MatMatMultTransposeNumeric_SeqAIJ_SeqAIJ, 2615 MatPtAPSymbolic_SeqAIJ_SeqAIJ, 2616 /*99*/ MatPtAPNumeric_SeqAIJ_SeqAIJ, 2617 0, 2618 0, 2619 MatConjugate_SeqAIJ, 2620 0, 2621 /*104*/MatSetValuesRow_SeqAIJ, 2622 MatRealPart_SeqAIJ, 2623 MatImaginaryPart_SeqAIJ, 2624 0, 2625 0, 2626 /*109*/0, 2627 0, 2628 MatGetRowMin_SeqAIJ, 2629 0, 2630 MatMissingDiagonal_SeqAIJ, 2631 /*114*/0, 2632 0, 2633 0, 2634 MatILUDTFactorSymbolic_SeqAIJ, 2635 MatILUDTFactorNumeric_SeqAIJ 2636 }; 2637 2638 EXTERN_C_BEGIN 2639 #undef __FUNCT__ 2640 #define __FUNCT__ "MatSeqAIJSetColumnIndices_SeqAIJ" 2641 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices) 2642 { 2643 Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2644 PetscInt i,nz,n; 2645 2646 PetscFunctionBegin; 2647 2648 nz = aij->maxnz; 2649 n = mat->rmap->n; 2650 for (i=0; i<nz; i++) { 2651 aij->j[i] = indices[i]; 2652 } 2653 aij->nz = nz; 2654 for (i=0; i<n; i++) { 2655 aij->ilen[i] = aij->imax[i]; 2656 } 2657 2658 PetscFunctionReturn(0); 2659 } 2660 EXTERN_C_END 2661 2662 #undef __FUNCT__ 2663 #define __FUNCT__ "MatSeqAIJSetColumnIndices" 2664 /*@ 2665 MatSeqAIJSetColumnIndices - Set the column indices for all the rows 2666 in the matrix. 2667 2668 Input Parameters: 2669 + mat - the SeqAIJ matrix 2670 - indices - the column indices 2671 2672 Level: advanced 2673 2674 Notes: 2675 This can be called if you have precomputed the nonzero structure of the 2676 matrix and want to provide it to the matrix object to improve the performance 2677 of the MatSetValues() operation. 2678 2679 You MUST have set the correct numbers of nonzeros per row in the call to 2680 MatCreateSeqAIJ(), and the columns indices MUST be sorted. 2681 2682 MUST be called before any calls to MatSetValues(); 2683 2684 The indices should start with zero, not one. 2685 2686 @*/ 2687 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices) 2688 { 2689 PetscErrorCode ierr,(*f)(Mat,PetscInt *); 2690 2691 PetscFunctionBegin; 2692 PetscValidHeaderSpecific(mat,MAT_COOKIE,1); 2693 PetscValidPointer(indices,2); 2694 ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqAIJSetColumnIndices_C",(void (**)(void))&f);CHKERRQ(ierr); 2695 if (f) { 2696 ierr = (*f)(mat,indices);CHKERRQ(ierr); 2697 } else { 2698 SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to set column indices"); 2699 } 2700 PetscFunctionReturn(0); 2701 } 2702 2703 /* ----------------------------------------------------------------------------------------*/ 2704 2705 EXTERN_C_BEGIN 2706 #undef __FUNCT__ 2707 #define __FUNCT__ "MatStoreValues_SeqAIJ" 2708 PetscErrorCode PETSCMAT_DLLEXPORT MatStoreValues_SeqAIJ(Mat mat) 2709 { 2710 Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2711 PetscErrorCode ierr; 2712 size_t nz = aij->i[mat->rmap->n]; 2713 2714 PetscFunctionBegin; 2715 if (aij->nonew != 1) { 2716 SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 2717 } 2718 2719 /* allocate space for values if not already there */ 2720 if (!aij->saved_values) { 2721 ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr); 2722 ierr = PetscLogObjectMemory(mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr); 2723 } 2724 2725 /* copy values over */ 2726 ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr); 2727 PetscFunctionReturn(0); 2728 } 2729 EXTERN_C_END 2730 2731 #undef __FUNCT__ 2732 #define __FUNCT__ "MatStoreValues" 2733 /*@ 2734 MatStoreValues - Stashes a copy of the matrix values; this allows, for 2735 example, reuse of the linear part of a Jacobian, while recomputing the 2736 nonlinear portion. 2737 2738 Collect on Mat 2739 2740 Input Parameters: 2741 . mat - the matrix (currently only AIJ matrices support this option) 2742 2743 Level: advanced 2744 2745 Common Usage, with SNESSolve(): 2746 $ Create Jacobian matrix 2747 $ Set linear terms into matrix 2748 $ Apply boundary conditions to matrix, at this time matrix must have 2749 $ final nonzero structure (i.e. setting the nonlinear terms and applying 2750 $ boundary conditions again will not change the nonzero structure 2751 $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 2752 $ ierr = MatStoreValues(mat); 2753 $ Call SNESSetJacobian() with matrix 2754 $ In your Jacobian routine 2755 $ ierr = MatRetrieveValues(mat); 2756 $ Set nonlinear terms in matrix 2757 2758 Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself: 2759 $ // build linear portion of Jacobian 2760 $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 2761 $ ierr = MatStoreValues(mat); 2762 $ loop over nonlinear iterations 2763 $ ierr = MatRetrieveValues(mat); 2764 $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian 2765 $ // call MatAssemblyBegin/End() on matrix 2766 $ Solve linear system with Jacobian 2767 $ endloop 2768 2769 Notes: 2770 Matrix must already be assemblied before calling this routine 2771 Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before 2772 calling this routine. 2773 2774 When this is called multiple times it overwrites the previous set of stored values 2775 and does not allocated additional space. 2776 2777 .seealso: MatRetrieveValues() 2778 2779 @*/ 2780 PetscErrorCode PETSCMAT_DLLEXPORT MatStoreValues(Mat mat) 2781 { 2782 PetscErrorCode ierr,(*f)(Mat); 2783 2784 PetscFunctionBegin; 2785 PetscValidHeaderSpecific(mat,MAT_COOKIE,1); 2786 if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 2787 if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2788 2789 ierr = PetscObjectQueryFunction((PetscObject)mat,"MatStoreValues_C",(void (**)(void))&f);CHKERRQ(ierr); 2790 if (f) { 2791 ierr = (*f)(mat);CHKERRQ(ierr); 2792 } else { 2793 SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to store values"); 2794 } 2795 PetscFunctionReturn(0); 2796 } 2797 2798 EXTERN_C_BEGIN 2799 #undef __FUNCT__ 2800 #define __FUNCT__ "MatRetrieveValues_SeqAIJ" 2801 PetscErrorCode PETSCMAT_DLLEXPORT MatRetrieveValues_SeqAIJ(Mat mat) 2802 { 2803 Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data; 2804 PetscErrorCode ierr; 2805 PetscInt nz = aij->i[mat->rmap->n]; 2806 2807 PetscFunctionBegin; 2808 if (aij->nonew != 1) { 2809 SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 2810 } 2811 if (!aij->saved_values) { 2812 SETERRQ(PETSC_ERR_ORDER,"Must call MatStoreValues(A);first"); 2813 } 2814 /* copy values over */ 2815 ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr); 2816 PetscFunctionReturn(0); 2817 } 2818 EXTERN_C_END 2819 2820 #undef __FUNCT__ 2821 #define __FUNCT__ "MatRetrieveValues" 2822 /*@ 2823 MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 2824 example, reuse of the linear part of a Jacobian, while recomputing the 2825 nonlinear portion. 2826 2827 Collect on Mat 2828 2829 Input Parameters: 2830 . mat - the matrix (currently on AIJ matrices support this option) 2831 2832 Level: advanced 2833 2834 .seealso: MatStoreValues() 2835 2836 @*/ 2837 PetscErrorCode PETSCMAT_DLLEXPORT MatRetrieveValues(Mat mat) 2838 { 2839 PetscErrorCode ierr,(*f)(Mat); 2840 2841 PetscFunctionBegin; 2842 PetscValidHeaderSpecific(mat,MAT_COOKIE,1); 2843 if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 2844 if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 2845 2846 ierr = PetscObjectQueryFunction((PetscObject)mat,"MatRetrieveValues_C",(void (**)(void))&f);CHKERRQ(ierr); 2847 if (f) { 2848 ierr = (*f)(mat);CHKERRQ(ierr); 2849 } else { 2850 SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to retrieve values"); 2851 } 2852 PetscFunctionReturn(0); 2853 } 2854 2855 2856 /* --------------------------------------------------------------------------------*/ 2857 #undef __FUNCT__ 2858 #define __FUNCT__ "MatCreateSeqAIJ" 2859 /*@C 2860 MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format 2861 (the default parallel PETSc format). For good matrix assembly performance 2862 the user should preallocate the matrix storage by setting the parameter nz 2863 (or the array nnz). By setting these parameters accurately, performance 2864 during matrix assembly can be increased by more than a factor of 50. 2865 2866 Collective on MPI_Comm 2867 2868 Input Parameters: 2869 + comm - MPI communicator, set to PETSC_COMM_SELF 2870 . m - number of rows 2871 . n - number of columns 2872 . nz - number of nonzeros per row (same for all rows) 2873 - nnz - array containing the number of nonzeros in the various rows 2874 (possibly different for each row) or PETSC_NULL 2875 2876 Output Parameter: 2877 . A - the matrix 2878 2879 It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 2880 MatXXXXSetPreallocation() paradgm instead of this routine directly. 2881 [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 2882 2883 Notes: 2884 If nnz is given then nz is ignored 2885 2886 The AIJ format (also called the Yale sparse matrix format or 2887 compressed row storage), is fully compatible with standard Fortran 77 2888 storage. That is, the stored row and column indices can begin at 2889 either one (as in Fortran) or zero. See the users' manual for details. 2890 2891 Specify the preallocated storage with either nz or nnz (not both). 2892 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 2893 allocation. For large problems you MUST preallocate memory or you 2894 will get TERRIBLE performance, see the users' manual chapter on matrices. 2895 2896 By default, this format uses inodes (identical nodes) when possible, to 2897 improve numerical efficiency of matrix-vector products and solves. We 2898 search for consecutive rows with the same nonzero structure, thereby 2899 reusing matrix information to achieve increased efficiency. 2900 2901 Options Database Keys: 2902 + -mat_no_inode - Do not use inodes 2903 . -mat_inode_limit <limit> - Sets inode limit (max limit=5) 2904 - -mat_aij_oneindex - Internally use indexing starting at 1 2905 rather than 0. Note that when calling MatSetValues(), 2906 the user still MUST index entries starting at 0! 2907 2908 Level: intermediate 2909 2910 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays() 2911 2912 @*/ 2913 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A) 2914 { 2915 PetscErrorCode ierr; 2916 2917 PetscFunctionBegin; 2918 ierr = MatCreate(comm,A);CHKERRQ(ierr); 2919 ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr); 2920 ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr); 2921 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,(PetscInt*)nnz);CHKERRQ(ierr); 2922 PetscFunctionReturn(0); 2923 } 2924 2925 #undef __FUNCT__ 2926 #define __FUNCT__ "MatSeqAIJSetPreallocation" 2927 /*@C 2928 MatSeqAIJSetPreallocation - For good matrix assembly performance 2929 the user should preallocate the matrix storage by setting the parameter nz 2930 (or the array nnz). By setting these parameters accurately, performance 2931 during matrix assembly can be increased by more than a factor of 50. 2932 2933 Collective on MPI_Comm 2934 2935 Input Parameters: 2936 + B - The matrix-free 2937 . nz - number of nonzeros per row (same for all rows) 2938 - nnz - array containing the number of nonzeros in the various rows 2939 (possibly different for each row) or PETSC_NULL 2940 2941 Notes: 2942 If nnz is given then nz is ignored 2943 2944 The AIJ format (also called the Yale sparse matrix format or 2945 compressed row storage), is fully compatible with standard Fortran 77 2946 storage. That is, the stored row and column indices can begin at 2947 either one (as in Fortran) or zero. See the users' manual for details. 2948 2949 Specify the preallocated storage with either nz or nnz (not both). 2950 Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory 2951 allocation. For large problems you MUST preallocate memory or you 2952 will get TERRIBLE performance, see the users' manual chapter on matrices. 2953 2954 You can call MatGetInfo() to get information on how effective the preallocation was; 2955 for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 2956 You can also run with the option -info and look for messages with the string 2957 malloc in them to see if additional memory allocation was needed. 2958 2959 Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix 2960 entries or columns indices 2961 2962 By default, this format uses inodes (identical nodes) when possible, to 2963 improve numerical efficiency of matrix-vector products and solves. We 2964 search for consecutive rows with the same nonzero structure, thereby 2965 reusing matrix information to achieve increased efficiency. 2966 2967 Options Database Keys: 2968 + -mat_no_inode - Do not use inodes 2969 . -mat_inode_limit <limit> - Sets inode limit (max limit=5) 2970 - -mat_aij_oneindex - Internally use indexing starting at 1 2971 rather than 0. Note that when calling MatSetValues(), 2972 the user still MUST index entries starting at 0! 2973 2974 Level: intermediate 2975 2976 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo() 2977 2978 @*/ 2979 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[]) 2980 { 2981 PetscErrorCode ierr,(*f)(Mat,PetscInt,const PetscInt[]); 2982 2983 PetscFunctionBegin; 2984 ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr); 2985 if (f) { 2986 ierr = (*f)(B,nz,nnz);CHKERRQ(ierr); 2987 } 2988 PetscFunctionReturn(0); 2989 } 2990 2991 EXTERN_C_BEGIN 2992 #undef __FUNCT__ 2993 #define __FUNCT__ "MatSeqAIJSetPreallocation_SeqAIJ" 2994 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,PetscInt *nnz) 2995 { 2996 Mat_SeqAIJ *b; 2997 PetscTruth skipallocation = PETSC_FALSE; 2998 PetscErrorCode ierr; 2999 PetscInt i; 3000 3001 PetscFunctionBegin; 3002 3003 if (nz == MAT_SKIP_ALLOCATION) { 3004 skipallocation = PETSC_TRUE; 3005 nz = 0; 3006 } 3007 3008 ierr = PetscLayoutSetBlockSize(B->rmap,1);CHKERRQ(ierr); 3009 ierr = PetscLayoutSetBlockSize(B->cmap,1);CHKERRQ(ierr); 3010 ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 3011 ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 3012 3013 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 3014 if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz); 3015 if (nnz) { 3016 for (i=0; i<B->rmap->n; i++) { 3017 if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]); 3018 if (nnz[i] > B->cmap->n) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %d value %d rowlength %d",i,nnz[i],B->cmap->n); 3019 } 3020 } 3021 3022 B->preallocated = PETSC_TRUE; 3023 b = (Mat_SeqAIJ*)B->data; 3024 3025 if (!skipallocation) { 3026 if (!b->imax) { 3027 ierr = PetscMalloc2(B->rmap->n,PetscInt,&b->imax,B->rmap->n,PetscInt,&b->ilen);CHKERRQ(ierr); 3028 ierr = PetscLogObjectMemory(B,2*B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 3029 } 3030 if (!nnz) { 3031 if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 3032 else if (nz <= 0) nz = 1; 3033 for (i=0; i<B->rmap->n; i++) b->imax[i] = nz; 3034 nz = nz*B->rmap->n; 3035 } else { 3036 nz = 0; 3037 for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz += nnz[i];} 3038 } 3039 /* b->ilen will count nonzeros in each row so far. */ 3040 for (i=0; i<B->rmap->n; i++) { b->ilen[i] = 0; } 3041 3042 /* allocate the matrix space */ 3043 ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr); 3044 ierr = PetscMalloc3(nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap->n+1,PetscInt,&b->i);CHKERRQ(ierr); 3045 ierr = PetscLogObjectMemory(B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr); 3046 b->i[0] = 0; 3047 for (i=1; i<B->rmap->n+1; i++) { 3048 b->i[i] = b->i[i-1] + b->imax[i-1]; 3049 } 3050 b->singlemalloc = PETSC_TRUE; 3051 b->free_a = PETSC_TRUE; 3052 b->free_ij = PETSC_TRUE; 3053 } else { 3054 b->free_a = PETSC_FALSE; 3055 b->free_ij = PETSC_FALSE; 3056 } 3057 3058 b->nz = 0; 3059 b->maxnz = nz; 3060 B->info.nz_unneeded = (double)b->maxnz; 3061 PetscFunctionReturn(0); 3062 } 3063 EXTERN_C_END 3064 3065 #undef __FUNCT__ 3066 #define __FUNCT__ "MatSeqAIJSetPreallocationCSR" 3067 /*@ 3068 MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format. 3069 3070 Input Parameters: 3071 + B - the matrix 3072 . i - the indices into j for the start of each row (starts with zero) 3073 . j - the column indices for each row (starts with zero) these must be sorted for each row 3074 - v - optional values in the matrix 3075 3076 Level: developer 3077 3078 The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays() 3079 3080 .keywords: matrix, aij, compressed row, sparse, sequential 3081 3082 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), SeqAIJ 3083 @*/ 3084 PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[]) 3085 { 3086 PetscErrorCode (*f)(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]); 3087 PetscErrorCode ierr; 3088 3089 PetscFunctionBegin; 3090 PetscValidHeaderSpecific(B,MAT_COOKIE,1); 3091 ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",(void (**)(void))&f);CHKERRQ(ierr); 3092 if (f) { 3093 ierr = (*f)(B,i,j,v);CHKERRQ(ierr); 3094 } 3095 PetscFunctionReturn(0); 3096 } 3097 3098 EXTERN_C_BEGIN 3099 #undef __FUNCT__ 3100 #define __FUNCT__ "MatSeqAIJSetPreallocationCSR_SeqAIJ" 3101 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[]) 3102 { 3103 PetscInt i; 3104 PetscInt m,n; 3105 PetscInt nz; 3106 PetscInt *nnz, nz_max = 0; 3107 PetscScalar *values; 3108 PetscErrorCode ierr; 3109 3110 PetscFunctionBegin; 3111 ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr); 3112 3113 if (Ii[0]) { 3114 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]); 3115 } 3116 ierr = PetscMalloc((m+1) * sizeof(PetscInt), &nnz);CHKERRQ(ierr); 3117 for(i = 0; i < m; i++) { 3118 nz = Ii[i+1]- Ii[i]; 3119 nz_max = PetscMax(nz_max, nz); 3120 if (nz < 0) { 3121 SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz); 3122 } 3123 nnz[i] = nz; 3124 } 3125 ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr); 3126 ierr = PetscFree(nnz);CHKERRQ(ierr); 3127 3128 if (v) { 3129 values = (PetscScalar*) v; 3130 } else { 3131 ierr = PetscMalloc(nz_max*sizeof(PetscScalar), &values);CHKERRQ(ierr); 3132 ierr = PetscMemzero(values, nz_max*sizeof(PetscScalar));CHKERRQ(ierr); 3133 } 3134 3135 for(i = 0; i < m; i++) { 3136 nz = Ii[i+1] - Ii[i]; 3137 ierr = MatSetValues_SeqAIJ(B, 1, &i, nz, J+Ii[i], values + (v ? Ii[i] : 0), INSERT_VALUES);CHKERRQ(ierr); 3138 } 3139 3140 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3141 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3142 3143 if (!v) { 3144 ierr = PetscFree(values);CHKERRQ(ierr); 3145 } 3146 PetscFunctionReturn(0); 3147 } 3148 EXTERN_C_END 3149 3150 #include "../src/mat/impls/dense/seq/dense.h" 3151 #include "private/petscaxpy.h" 3152 3153 #undef __FUNCT__ 3154 #define __FUNCT__ "MatMatMultNumeric_SeqDense_SeqAIJ" 3155 /* 3156 Computes (B'*A')' since computing B*A directly is untenable 3157 3158 n p p 3159 ( ) ( ) ( ) 3160 m ( A ) * n ( B ) = m ( C ) 3161 ( ) ( ) ( ) 3162 3163 */ 3164 PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C) 3165 { 3166 PetscErrorCode ierr; 3167 Mat_SeqDense *sub_a = (Mat_SeqDense*)A->data; 3168 Mat_SeqAIJ *sub_b = (Mat_SeqAIJ*)B->data; 3169 Mat_SeqDense *sub_c = (Mat_SeqDense*)C->data; 3170 PetscInt i,n,m,q,p; 3171 const PetscInt *ii,*idx; 3172 const PetscScalar *b,*a,*a_q; 3173 PetscScalar *c,*c_q; 3174 3175 PetscFunctionBegin; 3176 m = A->rmap->n; 3177 n = A->cmap->n; 3178 p = B->cmap->n; 3179 a = sub_a->v; 3180 b = sub_b->a; 3181 c = sub_c->v; 3182 ierr = PetscMemzero(c,m*p*sizeof(PetscScalar));CHKERRQ(ierr); 3183 3184 ii = sub_b->i; 3185 idx = sub_b->j; 3186 for (i=0; i<n; i++) { 3187 q = ii[i+1] - ii[i]; 3188 while (q-->0) { 3189 c_q = c + m*(*idx); 3190 a_q = a + m*i; 3191 PetscAXPY(c_q,*b,a_q,m); 3192 idx++; 3193 b++; 3194 } 3195 } 3196 PetscFunctionReturn(0); 3197 } 3198 3199 #undef __FUNCT__ 3200 #define __FUNCT__ "MatMatMultSymbolic_SeqDense_SeqAIJ" 3201 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat *C) 3202 { 3203 PetscErrorCode ierr; 3204 PetscInt m=A->rmap->n,n=B->cmap->n; 3205 Mat Cmat; 3206 3207 PetscFunctionBegin; 3208 if (A->cmap->n != B->rmap->n) SETERRQ2(PETSC_ERR_ARG_SIZ,"A->cmap->n %d != B->rmap->n %d\n",A->cmap->n,B->rmap->n); 3209 ierr = MatCreate(((PetscObject)A)->comm,&Cmat);CHKERRQ(ierr); 3210 ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr); 3211 ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr); 3212 ierr = MatSeqDenseSetPreallocation(Cmat,PETSC_NULL);CHKERRQ(ierr); 3213 Cmat->assembled = PETSC_TRUE; 3214 *C = Cmat; 3215 PetscFunctionReturn(0); 3216 } 3217 3218 /* ----------------------------------------------------------------*/ 3219 #undef __FUNCT__ 3220 #define __FUNCT__ "MatMatMult_SeqDense_SeqAIJ" 3221 PetscErrorCode MatMatMult_SeqDense_SeqAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 3222 { 3223 PetscErrorCode ierr; 3224 3225 PetscFunctionBegin; 3226 if (scall == MAT_INITIAL_MATRIX){ 3227 ierr = MatMatMultSymbolic_SeqDense_SeqAIJ(A,B,fill,C);CHKERRQ(ierr); 3228 } 3229 ierr = MatMatMultNumeric_SeqDense_SeqAIJ(A,B,*C);CHKERRQ(ierr); 3230 PetscFunctionReturn(0); 3231 } 3232 3233 3234 /*MC 3235 MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 3236 based on compressed sparse row format. 3237 3238 Options Database Keys: 3239 . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 3240 3241 Level: beginner 3242 3243 .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType 3244 M*/ 3245 3246 EXTERN_C_BEGIN 3247 #if defined(PETSC_HAVE_PASTIX) 3248 extern PetscErrorCode MatGetFactor_seqaij_pastix(Mat,MatFactorType,Mat*); 3249 #endif 3250 #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SCALAR_SINGLE) && !defined(PETSC_USE_SCALAR_MAT_SINGLE) 3251 extern PetscErrorCode MatGetFactor_seqaij_essl(Mat,MatFactorType,Mat *); 3252 #endif 3253 extern PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqAIJ_SeqCRL(Mat,MatType,MatReuse,Mat*); 3254 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_petsc(Mat,MatFactorType,Mat*); 3255 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactorAvailable_seqaij_petsc(Mat,MatFactorType,PetscTruth *); 3256 #if defined(PETSC_HAVE_MUMPS) 3257 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_mumps(Mat,MatFactorType,Mat*); 3258 #endif 3259 #if defined(PETSC_HAVE_SUPERLU) 3260 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_superlu(Mat,MatFactorType,Mat*); 3261 #endif 3262 #if defined(PETSC_HAVE_SUPERLU_DIST) 3263 extern PetscErrorCode MatGetFactor_seqaij_superlu_dist(Mat,MatFactorType,Mat*); 3264 #endif 3265 #if defined(PETSC_HAVE_SPOOLES) 3266 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_spooles(Mat,MatFactorType,Mat*); 3267 #endif 3268 #if defined(PETSC_HAVE_UMFPACK) 3269 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_umfpack(Mat,MatFactorType,Mat*); 3270 #endif 3271 #if defined(PETSC_HAVE_LUSOL) 3272 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_lusol(Mat,MatFactorType,Mat*); 3273 #endif 3274 EXTERN_C_END 3275 3276 3277 EXTERN_C_BEGIN 3278 #undef __FUNCT__ 3279 #define __FUNCT__ "MatCreate_SeqAIJ" 3280 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_SeqAIJ(Mat B) 3281 { 3282 Mat_SeqAIJ *b; 3283 PetscErrorCode ierr; 3284 PetscMPIInt size; 3285 3286 PetscFunctionBegin; 3287 ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr); 3288 if (size > 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1"); 3289 3290 ierr = PetscNewLog(B,Mat_SeqAIJ,&b);CHKERRQ(ierr); 3291 B->data = (void*)b; 3292 ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 3293 B->mapping = 0; 3294 b->row = 0; 3295 b->col = 0; 3296 b->icol = 0; 3297 b->reallocs = 0; 3298 b->ignorezeroentries = PETSC_FALSE; 3299 b->roworiented = PETSC_TRUE; 3300 b->nonew = 0; 3301 b->diag = 0; 3302 b->solve_work = 0; 3303 B->spptr = 0; 3304 b->saved_values = 0; 3305 b->idiag = 0; 3306 b->mdiag = 0; 3307 b->ssor_work = 0; 3308 b->omega = 1.0; 3309 b->fshift = 0.0; 3310 b->idiagvalid = PETSC_FALSE; 3311 b->keepnonzeropattern = PETSC_FALSE; 3312 b->xtoy = 0; 3313 b->XtoY = 0; 3314 b->compressedrow.use = PETSC_FALSE; 3315 b->compressedrow.nrows = B->rmap->n; 3316 b->compressedrow.i = PETSC_NULL; 3317 b->compressedrow.rindex = PETSC_NULL; 3318 b->compressedrow.checked = PETSC_FALSE; 3319 B->same_nonzero = PETSC_FALSE; 3320 3321 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 3322 #if defined(PETSC_HAVE_PASTIX) 3323 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_pastix_C", 3324 "MatGetFactor_seqaij_pastix", 3325 MatGetFactor_seqaij_pastix);CHKERRQ(ierr); 3326 #endif 3327 #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SCALAR_SINGLE) && !defined(PETSC_USE_SCALAR_MAT_SINGLE) 3328 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_essl_C", 3329 "MatGetFactor_seqaij_essl", 3330 MatGetFactor_seqaij_essl);CHKERRQ(ierr); 3331 #endif 3332 #if defined(PETSC_HAVE_SUPERLU) 3333 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_C", 3334 "MatGetFactor_seqaij_superlu", 3335 MatGetFactor_seqaij_superlu);CHKERRQ(ierr); 3336 #endif 3337 #if defined(PETSC_HAVE_SUPERLU_DIST) 3338 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_dist_C", 3339 "MatGetFactor_seqaij_superlu_dist", 3340 MatGetFactor_seqaij_superlu_dist);CHKERRQ(ierr); 3341 #endif 3342 #if defined(PETSC_HAVE_SPOOLES) 3343 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_spooles_C", 3344 "MatGetFactor_seqaij_spooles", 3345 MatGetFactor_seqaij_spooles);CHKERRQ(ierr); 3346 #endif 3347 #if defined(PETSC_HAVE_MUMPS) 3348 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_mumps_C", 3349 "MatGetFactor_seqaij_mumps", 3350 MatGetFactor_seqaij_mumps);CHKERRQ(ierr); 3351 #endif 3352 #if defined(PETSC_HAVE_UMFPACK) 3353 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_umfpack_C", 3354 "MatGetFactor_seqaij_umfpack", 3355 MatGetFactor_seqaij_umfpack);CHKERRQ(ierr); 3356 #endif 3357 #if defined(PETSC_HAVE_LUSOL) 3358 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_lusol_C", 3359 "MatGetFactor_seqaij_lusol", 3360 MatGetFactor_seqaij_lusol);CHKERRQ(ierr); 3361 #endif 3362 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_petsc_C", 3363 "MatGetFactor_seqaij_petsc", 3364 MatGetFactor_seqaij_petsc);CHKERRQ(ierr); 3365 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_petsc_C", 3366 "MatGetFactorAvailable_seqaij_petsc", 3367 MatGetFactorAvailable_seqaij_petsc);CHKERRQ(ierr); 3368 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C", 3369 "MatSeqAIJSetColumnIndices_SeqAIJ", 3370 MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr); 3371 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C", 3372 "MatStoreValues_SeqAIJ", 3373 MatStoreValues_SeqAIJ);CHKERRQ(ierr); 3374 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C", 3375 "MatRetrieveValues_SeqAIJ", 3376 MatRetrieveValues_SeqAIJ);CHKERRQ(ierr); 3377 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqsbaij_C", 3378 "MatConvert_SeqAIJ_SeqSBAIJ", 3379 MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr); 3380 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqbaij_C", 3381 "MatConvert_SeqAIJ_SeqBAIJ", 3382 MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr); 3383 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqcsrperm_C", 3384 "MatConvert_SeqAIJ_SeqCSRPERM", 3385 MatConvert_SeqAIJ_SeqCSRPERM);CHKERRQ(ierr); 3386 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqcrl_C", 3387 "MatConvert_SeqAIJ_SeqCRL", 3388 MatConvert_SeqAIJ_SeqCRL);CHKERRQ(ierr); 3389 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C", 3390 "MatIsTranspose_SeqAIJ", 3391 MatIsTranspose_SeqAIJ);CHKERRQ(ierr); 3392 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsHermitianTranspose_C", 3393 "MatIsHermitianTranspose_SeqAIJ", 3394 MatIsTranspose_SeqAIJ);CHKERRQ(ierr); 3395 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocation_C", 3396 "MatSeqAIJSetPreallocation_SeqAIJ", 3397 MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr); 3398 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C", 3399 "MatSeqAIJSetPreallocationCSR_SeqAIJ", 3400 MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr); 3401 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatReorderForNonzeroDiagonal_C", 3402 "MatReorderForNonzeroDiagonal_SeqAIJ", 3403 MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr); 3404 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMult_seqdense_seqaij_C", 3405 "MatMatMult_SeqDense_SeqAIJ", 3406 MatMatMult_SeqDense_SeqAIJ);CHKERRQ(ierr); 3407 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaij_C", 3408 "MatMatMultSymbolic_SeqDense_SeqAIJ", 3409 MatMatMultSymbolic_SeqDense_SeqAIJ);CHKERRQ(ierr); 3410 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultNumeric_seqdense_seqaij_C", 3411 "MatMatMultNumeric_SeqDense_SeqAIJ", 3412 MatMatMultNumeric_SeqDense_SeqAIJ);CHKERRQ(ierr); 3413 ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr); 3414 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 3415 PetscFunctionReturn(0); 3416 } 3417 EXTERN_C_END 3418 3419 #undef __FUNCT__ 3420 #define __FUNCT__ "MatDuplicateNoCreate_SeqAIJ" 3421 /* 3422 Given a matrix generated with MatGetFactor() duplicates all the information in A into B 3423 */ 3424 PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscTruth mallocmatspace) 3425 { 3426 Mat_SeqAIJ *c,*a = (Mat_SeqAIJ*)A->data; 3427 PetscErrorCode ierr; 3428 PetscInt i,m = A->rmap->n; 3429 3430 PetscFunctionBegin; 3431 c = (Mat_SeqAIJ*)C->data; 3432 3433 C->factor = A->factor; 3434 3435 c->row = 0; 3436 c->col = 0; 3437 c->icol = 0; 3438 c->reallocs = 0; 3439 3440 C->assembled = PETSC_TRUE; 3441 3442 ierr = PetscLayoutSetBlockSize(C->rmap,1);CHKERRQ(ierr); 3443 ierr = PetscLayoutSetBlockSize(C->cmap,1);CHKERRQ(ierr); 3444 ierr = PetscLayoutSetUp(C->rmap);CHKERRQ(ierr); 3445 ierr = PetscLayoutSetUp(C->cmap);CHKERRQ(ierr); 3446 3447 ierr = PetscMalloc2(m,PetscInt,&c->imax,m,PetscInt,&c->ilen);CHKERRQ(ierr); 3448 ierr = PetscLogObjectMemory(C, 2*m*sizeof(PetscInt));CHKERRQ(ierr); 3449 for (i=0; i<m; i++) { 3450 c->imax[i] = a->imax[i]; 3451 c->ilen[i] = a->ilen[i]; 3452 } 3453 3454 /* allocate the matrix space */ 3455 if (mallocmatspace){ 3456 ierr = PetscMalloc3(a->i[m],PetscScalar,&c->a,a->i[m],PetscInt,&c->j,m+1,PetscInt,&c->i);CHKERRQ(ierr); 3457 ierr = PetscLogObjectMemory(C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 3458 c->singlemalloc = PETSC_TRUE; 3459 ierr = PetscMemcpy(c->i,a->i,(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 3460 if (m > 0) { 3461 ierr = PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(PetscInt));CHKERRQ(ierr); 3462 if (cpvalues == MAT_COPY_VALUES) { 3463 ierr = PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr); 3464 } else { 3465 ierr = PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr); 3466 } 3467 } 3468 } 3469 3470 c->ignorezeroentries = a->ignorezeroentries; 3471 c->roworiented = a->roworiented; 3472 c->nonew = a->nonew; 3473 if (a->diag) { 3474 ierr = PetscMalloc((m+1)*sizeof(PetscInt),&c->diag);CHKERRQ(ierr); 3475 ierr = PetscLogObjectMemory(C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr); 3476 for (i=0; i<m; i++) { 3477 c->diag[i] = a->diag[i]; 3478 } 3479 } else c->diag = 0; 3480 c->solve_work = 0; 3481 c->saved_values = 0; 3482 c->idiag = 0; 3483 c->ssor_work = 0; 3484 c->keepnonzeropattern = a->keepnonzeropattern; 3485 c->free_a = PETSC_TRUE; 3486 c->free_ij = PETSC_TRUE; 3487 c->xtoy = 0; 3488 c->XtoY = 0; 3489 3490 c->nz = a->nz; 3491 c->maxnz = a->maxnz; 3492 C->preallocated = PETSC_TRUE; 3493 3494 c->compressedrow.use = a->compressedrow.use; 3495 c->compressedrow.nrows = a->compressedrow.nrows; 3496 c->compressedrow.checked = a->compressedrow.checked; 3497 if (a->compressedrow.checked && a->compressedrow.use){ 3498 i = a->compressedrow.nrows; 3499 ierr = PetscMalloc2(i+1,PetscInt,&c->compressedrow.i,i,PetscInt,&c->compressedrow.rindex);CHKERRQ(ierr); 3500 ierr = PetscMemcpy(c->compressedrow.i,a->compressedrow.i,(i+1)*sizeof(PetscInt));CHKERRQ(ierr); 3501 ierr = PetscMemcpy(c->compressedrow.rindex,a->compressedrow.rindex,i*sizeof(PetscInt));CHKERRQ(ierr); 3502 } else { 3503 c->compressedrow.use = PETSC_FALSE; 3504 c->compressedrow.i = PETSC_NULL; 3505 c->compressedrow.rindex = PETSC_NULL; 3506 } 3507 C->same_nonzero = A->same_nonzero; 3508 ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr); 3509 3510 ierr = PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr); 3511 PetscFunctionReturn(0); 3512 } 3513 3514 #undef __FUNCT__ 3515 #define __FUNCT__ "MatDuplicate_SeqAIJ" 3516 PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B) 3517 { 3518 PetscErrorCode ierr; 3519 PetscInt n = A->rmap->n; 3520 3521 PetscFunctionBegin; 3522 ierr = MatCreate(((PetscObject)A)->comm,B);CHKERRQ(ierr); 3523 ierr = MatSetSizes(*B,n,n,n,n);CHKERRQ(ierr); 3524 ierr = MatSetType(*B,MATSEQAIJ);CHKERRQ(ierr); 3525 ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr); 3526 PetscFunctionReturn(0); 3527 } 3528 3529 #undef __FUNCT__ 3530 #define __FUNCT__ "MatLoad_SeqAIJ" 3531 PetscErrorCode MatLoad_SeqAIJ(PetscViewer viewer, const MatType type,Mat *A) 3532 { 3533 Mat_SeqAIJ *a; 3534 Mat B; 3535 PetscErrorCode ierr; 3536 PetscInt i,sum,nz,header[4],*rowlengths = 0,M,N; 3537 int fd; 3538 PetscMPIInt size; 3539 MPI_Comm comm; 3540 3541 PetscFunctionBegin; 3542 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 3543 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 3544 if (size > 1) SETERRQ(PETSC_ERR_ARG_SIZ,"view must have one processor"); 3545 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 3546 ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr); 3547 if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file"); 3548 M = header[1]; N = header[2]; nz = header[3]; 3549 3550 if (nz < 0) { 3551 SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ"); 3552 } 3553 3554 /* read in row lengths */ 3555 ierr = PetscMalloc(M*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr); 3556 ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr); 3557 3558 /* check if sum of rowlengths is same as nz */ 3559 for (i=0,sum=0; i< M; i++) sum +=rowlengths[i]; 3560 if (sum != nz) SETERRQ2(PETSC_ERR_FILE_READ,"Inconsistant matrix data in file. no-nonzeros = %d, sum-row-lengths = %d\n",nz,sum); 3561 3562 /* create our matrix */ 3563 ierr = MatCreate(comm,&B);CHKERRQ(ierr); 3564 ierr = MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 3565 ierr = MatSetType(B,type);CHKERRQ(ierr); 3566 ierr = MatSeqAIJSetPreallocation_SeqAIJ(B,0,rowlengths);CHKERRQ(ierr); 3567 a = (Mat_SeqAIJ*)B->data; 3568 3569 ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT);CHKERRQ(ierr); 3570 3571 /* read in nonzero values */ 3572 ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);CHKERRQ(ierr); 3573 3574 /* set matrix "i" values */ 3575 a->i[0] = 0; 3576 for (i=1; i<= M; i++) { 3577 a->i[i] = a->i[i-1] + rowlengths[i-1]; 3578 a->ilen[i-1] = rowlengths[i-1]; 3579 } 3580 ierr = PetscFree(rowlengths);CHKERRQ(ierr); 3581 3582 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3583 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3584 *A = B; 3585 PetscFunctionReturn(0); 3586 } 3587 3588 #undef __FUNCT__ 3589 #define __FUNCT__ "MatEqual_SeqAIJ" 3590 PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscTruth* flg) 3591 { 3592 Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data; 3593 PetscErrorCode ierr; 3594 #if defined(PETSC_USE_COMPLEX) 3595 PetscInt k; 3596 #endif 3597 3598 PetscFunctionBegin; 3599 /* If the matrix dimensions are not equal,or no of nonzeros */ 3600 if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) { 3601 *flg = PETSC_FALSE; 3602 PetscFunctionReturn(0); 3603 } 3604 3605 /* if the a->i are the same */ 3606 ierr = PetscMemcmp(a->i,b->i,(A->rmap->n+1)*sizeof(PetscInt),flg);CHKERRQ(ierr); 3607 if (!*flg) PetscFunctionReturn(0); 3608 3609 /* if a->j are the same */ 3610 ierr = PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),flg);CHKERRQ(ierr); 3611 if (!*flg) PetscFunctionReturn(0); 3612 3613 /* if a->a are the same */ 3614 #if defined(PETSC_USE_COMPLEX) 3615 for (k=0; k<a->nz; k++){ 3616 if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])){ 3617 *flg = PETSC_FALSE; 3618 PetscFunctionReturn(0); 3619 } 3620 } 3621 #else 3622 ierr = PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);CHKERRQ(ierr); 3623 #endif 3624 PetscFunctionReturn(0); 3625 } 3626 3627 #undef __FUNCT__ 3628 #define __FUNCT__ "MatCreateSeqAIJWithArrays" 3629 /*@ 3630 MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format) 3631 provided by the user. 3632 3633 Collective on MPI_Comm 3634 3635 Input Parameters: 3636 + comm - must be an MPI communicator of size 1 3637 . m - number of rows 3638 . n - number of columns 3639 . i - row indices 3640 . j - column indices 3641 - a - matrix values 3642 3643 Output Parameter: 3644 . mat - the matrix 3645 3646 Level: intermediate 3647 3648 Notes: 3649 The i, j, and a arrays are not copied by this routine, the user must free these arrays 3650 once the matrix is destroyed 3651 3652 You cannot set new nonzero locations into this matrix, that will generate an error. 3653 3654 The i and j indices are 0 based 3655 3656 The format which is used for the sparse matrix input, is equivalent to a 3657 row-major ordering.. i.e for the following matrix, the input data expected is 3658 as shown: 3659 3660 1 0 0 3661 2 0 3 3662 4 5 6 3663 3664 i = {0,1,3,6} [size = nrow+1 = 3+1] 3665 j = {0,0,2,0,1,2} [size = nz = 6]; values must be sorted for each row 3666 v = {1,2,3,4,5,6} [size = nz = 6] 3667 3668 3669 .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR() 3670 3671 @*/ 3672 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat) 3673 { 3674 PetscErrorCode ierr; 3675 PetscInt ii; 3676 Mat_SeqAIJ *aij; 3677 #if defined(PETSC_USE_DEBUG) 3678 PetscInt jj; 3679 #endif 3680 3681 PetscFunctionBegin; 3682 if (i[0]) { 3683 SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 3684 } 3685 ierr = MatCreate(comm,mat);CHKERRQ(ierr); 3686 ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr); 3687 ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr); 3688 ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr); 3689 aij = (Mat_SeqAIJ*)(*mat)->data; 3690 ierr = PetscMalloc2(m,PetscInt,&aij->imax,m,PetscInt,&aij->ilen);CHKERRQ(ierr); 3691 3692 aij->i = i; 3693 aij->j = j; 3694 aij->a = a; 3695 aij->singlemalloc = PETSC_FALSE; 3696 aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 3697 aij->free_a = PETSC_FALSE; 3698 aij->free_ij = PETSC_FALSE; 3699 3700 for (ii=0; ii<m; ii++) { 3701 aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii]; 3702 #if defined(PETSC_USE_DEBUG) 3703 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]); 3704 for (jj=i[ii]+1; jj<i[ii+1]; jj++) { 3705 if (j[jj] < j[jj-1]) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual colum %D) in row %D is not sorted",jj-i[ii],j[jj],ii); 3706 if (j[jj] == j[jj]-1) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual colum %D) in row %D is identical to previous entry",jj-i[ii],j[jj],ii); 3707 } 3708 #endif 3709 } 3710 #if defined(PETSC_USE_DEBUG) 3711 for (ii=0; ii<aij->i[m]; ii++) { 3712 if (j[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]); 3713 if (j[ii] > n - 1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]); 3714 } 3715 #endif 3716 3717 ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3718 ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3719 PetscFunctionReturn(0); 3720 } 3721 3722 #undef __FUNCT__ 3723 #define __FUNCT__ "MatSetColoring_SeqAIJ" 3724 PetscErrorCode MatSetColoring_SeqAIJ(Mat A,ISColoring coloring) 3725 { 3726 PetscErrorCode ierr; 3727 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3728 3729 PetscFunctionBegin; 3730 if (coloring->ctype == IS_COLORING_GLOBAL) { 3731 ierr = ISColoringReference(coloring);CHKERRQ(ierr); 3732 a->coloring = coloring; 3733 } else if (coloring->ctype == IS_COLORING_GHOSTED) { 3734 PetscInt i,*larray; 3735 ISColoring ocoloring; 3736 ISColoringValue *colors; 3737 3738 /* set coloring for diagonal portion */ 3739 ierr = PetscMalloc(A->cmap->n*sizeof(PetscInt),&larray);CHKERRQ(ierr); 3740 for (i=0; i<A->cmap->n; i++) { 3741 larray[i] = i; 3742 } 3743 ierr = ISGlobalToLocalMappingApply(A->mapping,IS_GTOLM_MASK,A->cmap->n,larray,PETSC_NULL,larray);CHKERRQ(ierr); 3744 ierr = PetscMalloc(A->cmap->n*sizeof(ISColoringValue),&colors);CHKERRQ(ierr); 3745 for (i=0; i<A->cmap->n; i++) { 3746 colors[i] = coloring->colors[larray[i]]; 3747 } 3748 ierr = PetscFree(larray);CHKERRQ(ierr); 3749 ierr = ISColoringCreate(PETSC_COMM_SELF,coloring->n,A->cmap->n,colors,&ocoloring);CHKERRQ(ierr); 3750 a->coloring = ocoloring; 3751 } 3752 PetscFunctionReturn(0); 3753 } 3754 3755 #if defined(PETSC_HAVE_ADIC) 3756 EXTERN_C_BEGIN 3757 #include "adic/ad_utils.h" 3758 EXTERN_C_END 3759 3760 #undef __FUNCT__ 3761 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ" 3762 PetscErrorCode MatSetValuesAdic_SeqAIJ(Mat A,void *advalues) 3763 { 3764 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3765 PetscInt m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j,nlen; 3766 PetscScalar *v = a->a,*values = ((PetscScalar*)advalues)+1; 3767 ISColoringValue *color; 3768 3769 PetscFunctionBegin; 3770 if (!a->coloring) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix"); 3771 nlen = PetscADGetDerivTypeSize()/sizeof(PetscScalar); 3772 color = a->coloring->colors; 3773 /* loop over rows */ 3774 for (i=0; i<m; i++) { 3775 nz = ii[i+1] - ii[i]; 3776 /* loop over columns putting computed value into matrix */ 3777 for (j=0; j<nz; j++) { 3778 *v++ = values[color[*jj++]]; 3779 } 3780 values += nlen; /* jump to next row of derivatives */ 3781 } 3782 PetscFunctionReturn(0); 3783 } 3784 #endif 3785 3786 #undef __FUNCT__ 3787 #define __FUNCT__ "MatSetValuesAdifor_SeqAIJ" 3788 PetscErrorCode MatSetValuesAdifor_SeqAIJ(Mat A,PetscInt nl,void *advalues) 3789 { 3790 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3791 PetscInt m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j; 3792 MatScalar *v = a->a; 3793 PetscScalar *values = (PetscScalar *)advalues; 3794 ISColoringValue *color; 3795 3796 PetscFunctionBegin; 3797 if (!a->coloring) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix"); 3798 color = a->coloring->colors; 3799 /* loop over rows */ 3800 for (i=0; i<m; i++) { 3801 nz = ii[i+1] - ii[i]; 3802 /* loop over columns putting computed value into matrix */ 3803 for (j=0; j<nz; j++) { 3804 *v++ = values[color[*jj++]]; 3805 } 3806 values += nl; /* jump to next row of derivatives */ 3807 } 3808 PetscFunctionReturn(0); 3809 } 3810 3811 /* 3812 Special version for direct calls from Fortran 3813 */ 3814 #if defined(PETSC_HAVE_FORTRAN_CAPS) 3815 #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ 3816 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 3817 #define matsetvaluesseqaij_ matsetvaluesseqaij 3818 #endif 3819 3820 /* Change these macros so can be used in void function */ 3821 #undef CHKERRQ 3822 #define CHKERRQ(ierr) CHKERRABORT(((PetscObject)A)->comm,ierr) 3823 #undef SETERRQ2 3824 #define SETERRQ2(ierr,b,c,d) CHKERRABORT(((PetscObject)A)->comm,ierr) 3825 3826 EXTERN_C_BEGIN 3827 #undef __FUNCT__ 3828 #define __FUNCT__ "matsetvaluesseqaij_" 3829 void PETSC_STDCALL matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr) 3830 { 3831 Mat A = *AA; 3832 PetscInt m = *mm, n = *nn; 3833 InsertMode is = *isis; 3834 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3835 PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N; 3836 PetscInt *imax,*ai,*ailen; 3837 PetscErrorCode ierr; 3838 PetscInt *aj,nonew = a->nonew,lastcol = -1; 3839 MatScalar *ap,value,*aa; 3840 PetscTruth ignorezeroentries = a->ignorezeroentries; 3841 PetscTruth roworiented = a->roworiented; 3842 3843 PetscFunctionBegin; 3844 ierr = MatPreallocated(A);CHKERRQ(ierr); 3845 imax = a->imax; 3846 ai = a->i; 3847 ailen = a->ilen; 3848 aj = a->j; 3849 aa = a->a; 3850 3851 for (k=0; k<m; k++) { /* loop over added rows */ 3852 row = im[k]; 3853 if (row < 0) continue; 3854 #if defined(PETSC_USE_DEBUG) 3855 if (row >= A->rmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large"); 3856 #endif 3857 rp = aj + ai[row]; ap = aa + ai[row]; 3858 rmax = imax[row]; nrow = ailen[row]; 3859 low = 0; 3860 high = nrow; 3861 for (l=0; l<n; l++) { /* loop over added columns */ 3862 if (in[l] < 0) continue; 3863 #if defined(PETSC_USE_DEBUG) 3864 if (in[l] >= A->cmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Column too large"); 3865 #endif 3866 col = in[l]; 3867 if (roworiented) { 3868 value = v[l + k*n]; 3869 } else { 3870 value = v[k + l*m]; 3871 } 3872 if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 3873 3874 if (col <= lastcol) low = 0; else high = nrow; 3875 lastcol = col; 3876 while (high-low > 5) { 3877 t = (low+high)/2; 3878 if (rp[t] > col) high = t; 3879 else low = t; 3880 } 3881 for (i=low; i<high; i++) { 3882 if (rp[i] > col) break; 3883 if (rp[i] == col) { 3884 if (is == ADD_VALUES) ap[i] += value; 3885 else ap[i] = value; 3886 goto noinsert; 3887 } 3888 } 3889 if (value == 0.0 && ignorezeroentries) goto noinsert; 3890 if (nonew == 1) goto noinsert; 3891 if (nonew == -1) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix"); 3892 MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar); 3893 N = nrow++ - 1; a->nz++; high++; 3894 /* shift up all the later entries in this row */ 3895 for (ii=N; ii>=i; ii--) { 3896 rp[ii+1] = rp[ii]; 3897 ap[ii+1] = ap[ii]; 3898 } 3899 rp[i] = col; 3900 ap[i] = value; 3901 noinsert:; 3902 low = i + 1; 3903 } 3904 ailen[row] = nrow; 3905 } 3906 A->same_nonzero = PETSC_FALSE; 3907 PetscFunctionReturnVoid(); 3908 } 3909 EXTERN_C_END 3910