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