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