Actual source code: sbaij.c
1: #define PETSCMAT_DLL
3: /*
4: Defines the basic matrix operations for the SBAIJ (compressed row)
5: matrix storage format.
6: */
7: #include ../src/mat/impls/baij/seq/baij.h
8: #include ../src/mat/impls/sbaij/seq/sbaij.h
9: #include petscblaslapack.h
11: #include ../src/mat/impls/sbaij/seq/relax.h
12: #define USESHORT
13: #include ../src/mat/impls/sbaij/seq/relax.h
16: #define CHUNKSIZE 10
19: /*
20: Checks for missing diagonals
21: */
24: PetscErrorCode MatMissingDiagonal_SeqSBAIJ(Mat A,PetscTruth *missing,PetscInt *dd)
25: {
26: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
28: PetscInt *diag,*jj = a->j,i;
31: MatMarkDiagonal_SeqSBAIJ(A);
32: diag = a->diag;
33: *missing = PETSC_FALSE;
34: for (i=0; i<a->mbs; i++) {
35: if (jj[diag[i]] != i) {
36: *missing = PETSC_TRUE;
37: if (dd) *dd = i;
38: break;
39: }
40: }
41: return(0);
42: }
46: PetscErrorCode MatMarkDiagonal_SeqSBAIJ(Mat A)
47: {
48: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
50: PetscInt i;
53: if (!a->diag) {
54: PetscMalloc(a->mbs*sizeof(PetscInt),&a->diag);
55: PetscLogObjectMemory(A,a->mbs*sizeof(PetscInt));
56: a->free_diag = PETSC_TRUE;
57: }
58: for (i=0; i<a->mbs; i++) a->diag[i] = a->i[i];
59: return(0);
60: }
64: static PetscErrorCode MatGetRowIJ_SeqSBAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth blockcompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
65: {
66: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
67: PetscInt i,j,n = a->mbs,nz = a->i[n],bs = A->rmap->bs;
71: *nn = n;
72: if (!ia) return(0);
73: if (!blockcompressed) {
74: /* malloc & create the natural set of indices */
75: PetscMalloc2((n+1)*bs,PetscInt,ia,nz*bs,PetscInt,ja);
76: for (i=0; i<n+1; i++) {
77: for (j=0; j<bs; j++) {
78: *ia[i*bs+j] = a->i[i]*bs+j+oshift;
79: }
80: }
81: for (i=0; i<nz; i++) {
82: for (j=0; j<bs; j++) {
83: *ja[i*bs+j] = a->j[i]*bs+j+oshift;
84: }
85: }
86: } else { /* blockcompressed */
87: if (oshift == 1) {
88: /* temporarily add 1 to i and j indices */
89: for (i=0; i<nz; i++) a->j[i]++;
90: for (i=0; i<n+1; i++) a->i[i]++;
91: }
92: *ia = a->i; *ja = a->j;
93: }
95: return(0);
96: }
100: static PetscErrorCode MatRestoreRowIJ_SeqSBAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth blockcompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
101: {
102: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
103: PetscInt i,n = a->mbs,nz = a->i[n];
107: if (!ia) return(0);
109: if (!blockcompressed) {
110: PetscFree2(*ia,*ja);
111: } else if (oshift == 1) { /* blockcompressed */
112: for (i=0; i<nz; i++) a->j[i]--;
113: for (i=0; i<n+1; i++) a->i[i]--;
114: }
116: return(0);
117: }
121: PetscErrorCode MatDestroy_SeqSBAIJ(Mat A)
122: {
123: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
127: #if defined(PETSC_USE_LOG)
128: PetscLogObjectState((PetscObject)A,"Rows=%D, NZ=%D",A->rmap->N,a->nz);
129: #endif
130: MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);
131: if (a->free_diag){PetscFree(a->diag);}
132: if (a->row) {ISDestroy(a->row);}
133: if (a->col){ISDestroy(a->col);}
134: if (a->icol) {ISDestroy(a->icol);}
135: if (a->idiag) {PetscFree(a->idiag);}
136: if (a->inode.size) {PetscFree(a->inode.size);}
137: if (a->free_diag) {PetscFree(a->diag);}
138: if (a->free_imax_ilen) {PetscFree2(a->imax,a->ilen);}
139: PetscFree(a->solve_work);
140: PetscFree(a->sor_work);
141: PetscFree(a->solves_work);
142: PetscFree(a->mult_work);
143: PetscFree(a->saved_values);
144: PetscFree(a->xtoy);
145: if (a->free_jshort) {PetscFree(a->jshort);}
146: PetscFree(a->inew);
147: if (a->parent) {MatDestroy(a->parent);}
148: PetscFree(a);
150: PetscObjectChangeTypeName((PetscObject)A,0);
151: PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C","",PETSC_NULL);
152: PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C","",PETSC_NULL);
153: PetscObjectComposeFunction((PetscObject)A,"MatSeqSBAIJSetColumnIndices_C","",PETSC_NULL);
154: PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqsbaij_seqaij_C","",PETSC_NULL);
155: PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqsbaij_seqbaij_C","",PETSC_NULL);
156: PetscObjectComposeFunction((PetscObject)A,"MatSeqSBAIJSetPreallocation_C","",PETSC_NULL);
157: return(0);
158: }
162: PetscErrorCode MatSetOption_SeqSBAIJ(Mat A,MatOption op,PetscTruth flg)
163: {
164: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
168: switch (op) {
169: case MAT_ROW_ORIENTED:
170: a->roworiented = flg;
171: break;
172: case MAT_KEEP_NONZERO_PATTERN:
173: a->keepnonzeropattern = flg;
174: break;
175: case MAT_NEW_NONZERO_LOCATIONS:
176: a->nonew = (flg ? 0 : 1);
177: break;
178: case MAT_NEW_NONZERO_LOCATION_ERR:
179: a->nonew = (flg ? -1 : 0);
180: break;
181: case MAT_NEW_NONZERO_ALLOCATION_ERR:
182: a->nonew = (flg ? -2 : 0);
183: break;
184: case MAT_UNUSED_NONZERO_LOCATION_ERR:
185: a->nounused = (flg ? -1 : 0);
186: break;
187: case MAT_NEW_DIAGONALS:
188: case MAT_IGNORE_OFF_PROC_ENTRIES:
189: case MAT_USE_HASH_TABLE:
190: PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);
191: break;
192: case MAT_HERMITIAN:
193: if (!A->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must call MatAssemblyEnd() first");
194: if (A->cmap->n < 65536 && A->cmap->bs == 1) {
195: A->ops->mult = MatMult_SeqSBAIJ_1_Hermitian_ushort;
196: } else if (A->cmap->bs == 1) {
197: A->ops->mult = MatMult_SeqSBAIJ_1_Hermitian;
198: } else SETERRQ(PETSC_ERR_SUP,"No support for Hermitian with block size greater than 1");
199: break;
200: case MAT_SYMMETRIC:
201: case MAT_STRUCTURALLY_SYMMETRIC:
202: case MAT_SYMMETRY_ETERNAL:
203: if (!flg) SETERRQ(PETSC_ERR_SUP,"Matrix must be symmetric");
204: PetscInfo1(A,"Option %s not relevent\n",MatOptions[op]);
205: break;
206: case MAT_IGNORE_LOWER_TRIANGULAR:
207: a->ignore_ltriangular = flg;
208: break;
209: case MAT_ERROR_LOWER_TRIANGULAR:
210: a->ignore_ltriangular = flg;
211: break;
212: case MAT_GETROW_UPPERTRIANGULAR:
213: a->getrow_utriangular = flg;
214: break;
215: default:
216: SETERRQ1(PETSC_ERR_SUP,"unknown option %d",op);
217: }
218: return(0);
219: }
223: PetscErrorCode MatGetRow_SeqSBAIJ(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **v)
224: {
225: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
227: PetscInt itmp,i,j,k,M,*ai,*aj,bs,bn,bp,*cols_i,bs2;
228: MatScalar *aa,*aa_i;
229: PetscScalar *v_i;
232: if (A && !a->getrow_utriangular) SETERRQ(PETSC_ERR_SUP,"MatGetRow is not supported for SBAIJ matrix format. Getting the upper triangular part of row, run with -mat_getrow_uppertriangular, call MatSetOption(mat,MAT_GETROW_UPPERTRIANGULAR,PETSC_TRUE) or MatGetRowUpperTriangular()");
233: /* Get the upper triangular part of the row */
234: bs = A->rmap->bs;
235: ai = a->i;
236: aj = a->j;
237: aa = a->a;
238: bs2 = a->bs2;
239:
240: if (row < 0 || row >= A->rmap->N) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Row %D out of range", row);
241:
242: bn = row/bs; /* Block number */
243: bp = row % bs; /* Block position */
244: M = ai[bn+1] - ai[bn];
245: *ncols = bs*M;
246:
247: if (v) {
248: *v = 0;
249: if (*ncols) {
250: PetscMalloc((*ncols+row)*sizeof(PetscScalar),v);
251: for (i=0; i<M; i++) { /* for each block in the block row */
252: v_i = *v + i*bs;
253: aa_i = aa + bs2*(ai[bn] + i);
254: for (j=bp,k=0; j<bs2; j+=bs,k++) {v_i[k] = aa_i[j];}
255: }
256: }
257: }
258:
259: if (cols) {
260: *cols = 0;
261: if (*ncols) {
262: PetscMalloc((*ncols+row)*sizeof(PetscInt),cols);
263: for (i=0; i<M; i++) { /* for each block in the block row */
264: cols_i = *cols + i*bs;
265: itmp = bs*aj[ai[bn] + i];
266: for (j=0; j<bs; j++) {cols_i[j] = itmp++;}
267: }
268: }
269: }
270:
271: /*search column A(0:row-1,row) (=A(row,0:row-1)). Could be expensive! */
272: /* this segment is currently removed, so only entries in the upper triangle are obtained */
273: #ifdef column_search
274: v_i = *v + M*bs;
275: cols_i = *cols + M*bs;
276: for (i=0; i<bn; i++){ /* for each block row */
277: M = ai[i+1] - ai[i];
278: for (j=0; j<M; j++){
279: itmp = aj[ai[i] + j]; /* block column value */
280: if (itmp == bn){
281: aa_i = aa + bs2*(ai[i] + j) + bs*bp;
282: for (k=0; k<bs; k++) {
283: *cols_i++ = i*bs+k;
284: *v_i++ = aa_i[k];
285: }
286: *ncols += bs;
287: break;
288: }
289: }
290: }
291: #endif
292: return(0);
293: }
297: PetscErrorCode MatRestoreRow_SeqSBAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
298: {
300:
302: if (idx) {PetscFree(*idx);}
303: if (v) {PetscFree(*v);}
304: return(0);
305: }
309: PetscErrorCode MatGetRowUpperTriangular_SeqSBAIJ(Mat A)
310: {
311: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
314: a->getrow_utriangular = PETSC_TRUE;
315: return(0);
316: }
319: PetscErrorCode MatRestoreRowUpperTriangular_SeqSBAIJ(Mat A)
320: {
321: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
324: a->getrow_utriangular = PETSC_FALSE;
325: return(0);
326: }
330: PetscErrorCode MatTranspose_SeqSBAIJ(Mat A,MatReuse reuse,Mat *B)
331: {
334: if (reuse == MAT_INITIAL_MATRIX || *B != A) {
335: MatDuplicate(A,MAT_COPY_VALUES,B);
336: }
337: return(0);
338: }
342: static PetscErrorCode MatView_SeqSBAIJ_ASCII(Mat A,PetscViewer viewer)
343: {
344: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
345: PetscErrorCode ierr;
346: PetscInt i,j,bs = A->rmap->bs,k,l,bs2=a->bs2;
347: const char *name;
348: PetscViewerFormat format;
349:
351: PetscObjectGetName((PetscObject)A,&name);
352: PetscViewerGetFormat(viewer,&format);
353: if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
354: PetscViewerASCIIPrintf(viewer," block size is %D\n",bs);
355: } else if (format == PETSC_VIEWER_ASCII_MATLAB) {
356: Mat aij;
358: if (A->factor && bs>1){
359: PetscPrintf(PETSC_COMM_SELF,"Warning: matrix is factored with bs>1. MatView() with PETSC_VIEWER_ASCII_MATLAB is not supported and ignored!\n");
360: return(0);
361: }
362: MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&aij);
363: MatView(aij,viewer);
364: MatDestroy(aij);
365: } else if (format == PETSC_VIEWER_ASCII_COMMON) {
366: PetscViewerASCIIUseTabs(viewer,PETSC_NO);
367: for (i=0; i<a->mbs; i++) {
368: for (j=0; j<bs; j++) {
369: PetscViewerASCIIPrintf(viewer,"row %D:",i*bs+j);
370: for (k=a->i[i]; k<a->i[i+1]; k++) {
371: for (l=0; l<bs; l++) {
372: #if defined(PETSC_USE_COMPLEX)
373: if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
374: PetscViewerASCIIPrintf(viewer," (%D, %G + %G i) ",bs*a->j[k]+l,
375: PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));
376: } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0 && PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
377: PetscViewerASCIIPrintf(viewer," (%D, %G - %G i) ",bs*a->j[k]+l,
378: PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));
379: } else if (PetscRealPart(a->a[bs2*k + l*bs + j]) != 0.0) {
380: PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));
381: }
382: #else
383: if (a->a[bs2*k + l*bs + j] != 0.0) {
384: PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);
385: }
386: #endif
387: }
388: }
389: PetscViewerASCIIPrintf(viewer,"\n");
390: }
391: }
392: PetscViewerASCIIUseTabs(viewer,PETSC_YES);
393: } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
394: return(0);
395: } else {
396: if (A->factor && bs>1){
397: PetscPrintf(PETSC_COMM_SELF,"Warning: matrix is factored. MatView_SeqSBAIJ_ASCII() may not display complete or logically correct entries!\n");
398: }
399: PetscViewerASCIIUseTabs(viewer,PETSC_NO);
400: for (i=0; i<a->mbs; i++) {
401: for (j=0; j<bs; j++) {
402: PetscViewerASCIIPrintf(viewer,"row %D:",i*bs+j);
403: for (k=a->i[i]; k<a->i[i+1]; k++) {
404: for (l=0; l<bs; l++) {
405: #if defined(PETSC_USE_COMPLEX)
406: if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) > 0.0) {
407: PetscViewerASCIIPrintf(viewer," (%D, %G + %G i) ",bs*a->j[k]+l,
408: PetscRealPart(a->a[bs2*k + l*bs + j]),PetscImaginaryPart(a->a[bs2*k + l*bs + j]));
409: } else if (PetscImaginaryPart(a->a[bs2*k + l*bs + j]) < 0.0) {
410: PetscViewerASCIIPrintf(viewer," (%D, %G - %G i) ",bs*a->j[k]+l,
411: PetscRealPart(a->a[bs2*k + l*bs + j]),-PetscImaginaryPart(a->a[bs2*k + l*bs + j]));
412: } else {
413: PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,PetscRealPart(a->a[bs2*k + l*bs + j]));
414: }
415: #else
416: PetscViewerASCIIPrintf(viewer," (%D, %G) ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);
417: #endif
418: }
419: }
420: PetscViewerASCIIPrintf(viewer,"\n");
421: }
422: }
423: PetscViewerASCIIUseTabs(viewer,PETSC_YES);
424: }
425: PetscViewerFlush(viewer);
426: return(0);
427: }
431: static PetscErrorCode MatView_SeqSBAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
432: {
433: Mat A = (Mat) Aa;
434: Mat_SeqSBAIJ *a=(Mat_SeqSBAIJ*)A->data;
436: PetscInt row,i,j,k,l,mbs=a->mbs,color,bs=A->rmap->bs,bs2=a->bs2;
437: PetscMPIInt rank;
438: PetscReal xl,yl,xr,yr,x_l,x_r,y_l,y_r;
439: MatScalar *aa;
440: MPI_Comm comm;
441: PetscViewer viewer;
442:
444: /*
445: This is nasty. If this is called from an originally parallel matrix
446: then all processes call this,but only the first has the matrix so the
447: rest should return immediately.
448: */
449: PetscObjectGetComm((PetscObject)draw,&comm);
450: MPI_Comm_rank(comm,&rank);
451: if (rank) return(0);
452:
453: PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);
454:
455: PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);
456: PetscDrawString(draw, .3*(xl+xr), .3*(yl+yr), PETSC_DRAW_BLACK, "symmetric");
457:
458: /* loop over matrix elements drawing boxes */
459: color = PETSC_DRAW_BLUE;
460: for (i=0,row=0; i<mbs; i++,row+=bs) {
461: for (j=a->i[i]; j<a->i[i+1]; j++) {
462: y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0;
463: x_l = a->j[j]*bs; x_r = x_l + 1.0;
464: aa = a->a + j*bs2;
465: for (k=0; k<bs; k++) {
466: for (l=0; l<bs; l++) {
467: if (PetscRealPart(*aa++) >= 0.) continue;
468: PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);
469: }
470: }
471: }
472: }
473: color = PETSC_DRAW_CYAN;
474: for (i=0,row=0; i<mbs; i++,row+=bs) {
475: for (j=a->i[i]; j<a->i[i+1]; j++) {
476: y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0;
477: x_l = a->j[j]*bs; x_r = x_l + 1.0;
478: aa = a->a + j*bs2;
479: for (k=0; k<bs; k++) {
480: for (l=0; l<bs; l++) {
481: if (PetscRealPart(*aa++) != 0.) continue;
482: PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);
483: }
484: }
485: }
486: }
487:
488: color = PETSC_DRAW_RED;
489: for (i=0,row=0; i<mbs; i++,row+=bs) {
490: for (j=a->i[i]; j<a->i[i+1]; j++) {
491: y_l = A->rmap->N - row - 1.0; y_r = y_l + 1.0;
492: x_l = a->j[j]*bs; x_r = x_l + 1.0;
493: aa = a->a + j*bs2;
494: for (k=0; k<bs; k++) {
495: for (l=0; l<bs; l++) {
496: if (PetscRealPart(*aa++) <= 0.) continue;
497: PetscDrawRectangle(draw,x_l+k,y_l-l,x_r+k,y_r-l,color,color,color,color);
498: }
499: }
500: }
501: }
502: return(0);
503: }
507: static PetscErrorCode MatView_SeqSBAIJ_Draw(Mat A,PetscViewer viewer)
508: {
510: PetscReal xl,yl,xr,yr,w,h;
511: PetscDraw draw;
512: PetscTruth isnull;
513:
515: PetscViewerDrawGetDraw(viewer,0,&draw);
516: PetscDrawIsNull(draw,&isnull); if (isnull) return(0);
517:
518: PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);
519: xr = A->rmap->N; yr = A->rmap->N; h = yr/10.0; w = xr/10.0;
520: xr += w; yr += h; xl = -w; yl = -h;
521: PetscDrawSetCoordinates(draw,xl,yl,xr,yr);
522: PetscDrawZoom(draw,MatView_SeqSBAIJ_Draw_Zoom,A);
523: PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);
524: return(0);
525: }
529: PetscErrorCode MatView_SeqSBAIJ(Mat A,PetscViewer viewer)
530: {
532: PetscTruth iascii,isdraw;
533: FILE *file = 0;
536: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
537: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);
538: if (iascii){
539: MatView_SeqSBAIJ_ASCII(A,viewer);
540: } else if (isdraw) {
541: MatView_SeqSBAIJ_Draw(A,viewer);
542: } else {
543: Mat B;
544: MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);
545: MatView(B,viewer);
546: MatDestroy(B);
547: PetscViewerBinaryGetInfoPointer(viewer,&file);
548: if (file) {
549: fprintf(file,"-matload_block_size %d\n",(int)A->rmap->bs);
550: }
551: }
552: return(0);
553: }
558: PetscErrorCode MatGetValues_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
559: {
560: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
561: PetscInt *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
562: PetscInt *ai = a->i,*ailen = a->ilen;
563: PetscInt brow,bcol,ridx,cidx,bs=A->rmap->bs,bs2=a->bs2;
564: MatScalar *ap,*aa = a->a;
565:
567: for (k=0; k<m; k++) { /* loop over rows */
568: row = im[k]; brow = row/bs;
569: if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
570: if (row >= A->rmap->N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->N-1);
571: rp = aj + ai[brow] ; ap = aa + bs2*ai[brow] ;
572: nrow = ailen[brow];
573: for (l=0; l<n; l++) { /* loop over columns */
574: if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
575: if (in[l] >= A->cmap->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
576: col = in[l] ;
577: bcol = col/bs;
578: cidx = col%bs;
579: ridx = row%bs;
580: high = nrow;
581: low = 0; /* assume unsorted */
582: while (high-low > 5) {
583: t = (low+high)/2;
584: if (rp[t] > bcol) high = t;
585: else low = t;
586: }
587: for (i=low; i<high; i++) {
588: if (rp[i] > bcol) break;
589: if (rp[i] == bcol) {
590: *v++ = ap[bs2*i+bs*cidx+ridx];
591: goto finished;
592: }
593: }
594: *v++ = 0.0;
595: finished:;
596: }
597: }
598: return(0);
599: }
604: PetscErrorCode MatSetValuesBlocked_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
605: {
606: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
607: PetscErrorCode ierr;
608: PetscInt *rp,k,low,high,t,ii,jj,row,nrow,i,col,l,rmax,N,lastcol = -1;
609: PetscInt *imax=a->imax,*ai=a->i,*ailen=a->ilen;
610: PetscInt *aj=a->j,nonew=a->nonew,bs2=a->bs2,bs=A->rmap->bs,stepval;
611: PetscTruth roworiented=a->roworiented;
612: const PetscScalar *value = v;
613: MatScalar *ap,*aa = a->a,*bap;
614:
616: if (roworiented) {
617: stepval = (n-1)*bs;
618: } else {
619: stepval = (m-1)*bs;
620: }
621: for (k=0; k<m; k++) { /* loop over added rows */
622: row = im[k];
623: if (row < 0) continue;
624: #if defined(PETSC_USE_DEBUG)
625: if (row >= a->mbs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,a->mbs-1);
626: #endif
627: rp = aj + ai[row];
628: ap = aa + bs2*ai[row];
629: rmax = imax[row];
630: nrow = ailen[row];
631: low = 0;
632: high = nrow;
633: for (l=0; l<n; l++) { /* loop over added columns */
634: if (in[l] < 0) continue;
635: col = in[l];
636: #if defined(PETSC_USE_DEBUG)
637: if (col >= a->nbs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",col,a->nbs-1);
638: #endif
639: if (col < row) {
640: if (a->ignore_ltriangular) {
641: continue; /* ignore lower triangular block */
642: } else {
643: SETERRQ(PETSC_ERR_USER,"Lower triangular value cannot be set for sbaij format. Ignoring these values, run with -mat_ignore_lower_triangular or call MatSetOption(mat,MAT_IGNORE_LOWER_TRIANGULAR,PETSC_TRUE)");
644: }
645: }
646: if (roworiented) {
647: value = v + k*(stepval+bs)*bs + l*bs;
648: } else {
649: value = v + l*(stepval+bs)*bs + k*bs;
650: }
651: if (col <= lastcol) low = 0; else high = nrow;
652: lastcol = col;
653: while (high-low > 7) {
654: t = (low+high)/2;
655: if (rp[t] > col) high = t;
656: else low = t;
657: }
658: for (i=low; i<high; i++) {
659: if (rp[i] > col) break;
660: if (rp[i] == col) {
661: bap = ap + bs2*i;
662: if (roworiented) {
663: if (is == ADD_VALUES) {
664: for (ii=0; ii<bs; ii++,value+=stepval) {
665: for (jj=ii; jj<bs2; jj+=bs) {
666: bap[jj] += *value++;
667: }
668: }
669: } else {
670: for (ii=0; ii<bs; ii++,value+=stepval) {
671: for (jj=ii; jj<bs2; jj+=bs) {
672: bap[jj] = *value++;
673: }
674: }
675: }
676: } else {
677: if (is == ADD_VALUES) {
678: for (ii=0; ii<bs; ii++,value+=stepval) {
679: for (jj=0; jj<bs; jj++) {
680: *bap++ += *value++;
681: }
682: }
683: } else {
684: for (ii=0; ii<bs; ii++,value+=stepval) {
685: for (jj=0; jj<bs; jj++) {
686: *bap++ = *value++;
687: }
688: }
689: }
690: }
691: goto noinsert2;
692: }
693: }
694: if (nonew == 1) goto noinsert2;
695: if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col);
696: MatSeqXAIJReallocateAIJ(A,a->mbs,bs2,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
697: N = nrow++ - 1; high++;
698: /* shift up all the later entries in this row */
699: for (ii=N; ii>=i; ii--) {
700: rp[ii+1] = rp[ii];
701: PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));
702: }
703: if (N >= i) {
704: PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));
705: }
706: rp[i] = col;
707: bap = ap + bs2*i;
708: if (roworiented) {
709: for (ii=0; ii<bs; ii++,value+=stepval) {
710: for (jj=ii; jj<bs2; jj+=bs) {
711: bap[jj] = *value++;
712: }
713: }
714: } else {
715: for (ii=0; ii<bs; ii++,value+=stepval) {
716: for (jj=0; jj<bs; jj++) {
717: *bap++ = *value++;
718: }
719: }
720: }
721: noinsert2:;
722: low = i;
723: }
724: ailen[row] = nrow;
725: }
726: return(0);
727: }
729: /*
730: This is not yet used
731: */
734: PetscErrorCode MatAssemblyEnd_SeqSBAIJ_SeqAIJ_Inode(Mat A)
735: {
736: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
737: PetscErrorCode ierr;
738: const PetscInt *ai = a->i, *aj = a->j,*cols;
739: PetscInt i = 0,j,blk_size,m = A->rmap->n,node_count = 0,nzx,nzy,*ns,row,nz,cnt,cnt2,*counts;
740: PetscTruth flag;
743: PetscMalloc(m*sizeof(PetscInt),&ns);
744: while (i < m){
745: nzx = ai[i+1] - ai[i]; /* Number of nonzeros */
746: /* Limits the number of elements in a node to 'a->inode.limit' */
747: for (j=i+1,blk_size=1; j<m && blk_size <a->inode.limit; ++j,++blk_size) {
748: nzy = ai[j+1] - ai[j];
749: if (nzy != (nzx - j + i)) break;
750: PetscMemcmp(aj + ai[i] + j - i,aj + ai[j],nzy*sizeof(PetscInt),&flag);
751: if (!flag) break;
752: }
753: ns[node_count++] = blk_size;
754: i = j;
755: }
756: if (!a->inode.size && m && node_count > .9*m) {
757: PetscFree(ns);
758: PetscInfo2(A,"Found %D nodes out of %D rows. Not using Inode routines\n",node_count,m);
759: } else {
760: a->inode.node_count = node_count;
761: PetscMalloc(node_count*sizeof(PetscInt),&a->inode.size);
762: PetscLogObjectMemory(A,node_count*sizeof(PetscInt));
763: PetscMemcpy(a->inode.size,ns,node_count*sizeof(PetscInt));
764: PetscFree(ns);
765: PetscInfo3(A,"Found %D nodes of %D. Limit used: %D. Using Inode routines\n",node_count,m,a->inode.limit);
766:
767: /* count collections of adjacent columns in each inode */
768: row = 0;
769: cnt = 0;
770: for (i=0; i<node_count; i++) {
771: cols = aj + ai[row] + a->inode.size[i];
772: nz = ai[row+1] - ai[row] - a->inode.size[i];
773: for (j=1; j<nz; j++) {
774: if (cols[j] != cols[j-1]+1) {
775: cnt++;
776: }
777: }
778: cnt++;
779: row += a->inode.size[i];
780: }
781: PetscMalloc(2*cnt*sizeof(PetscInt),&counts);
782: cnt = 0;
783: row = 0;
784: for (i=0; i<node_count; i++) {
785: cols = aj + ai[row] + a->inode.size[i];
786: CHKMEMQ;
787: counts[2*cnt] = cols[0];
788: CHKMEMQ;
789: nz = ai[row+1] - ai[row] - a->inode.size[i];
790: cnt2 = 1;
791: for (j=1; j<nz; j++) {
792: if (cols[j] != cols[j-1]+1) {
793: CHKMEMQ;
794: counts[2*(cnt++)+1] = cnt2;
795: counts[2*cnt] = cols[j];
796: CHKMEMQ;
797: cnt2 = 1;
798: } else cnt2++;
799: }
800: CHKMEMQ;
801: counts[2*(cnt++)+1] = cnt2;
802: CHKMEMQ;
803: row += a->inode.size[i];
804: }
805: PetscIntView(2*cnt,counts,0);
806: }
807: return(0);
808: }
812: PetscErrorCode MatAssemblyEnd_SeqSBAIJ(Mat A,MatAssemblyType mode)
813: {
814: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
816: PetscInt fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
817: PetscInt m = A->rmap->N,*ip,N,*ailen = a->ilen;
818: PetscInt mbs = a->mbs,bs2 = a->bs2,rmax = 0;
819: MatScalar *aa = a->a,*ap;
820:
822: if (mode == MAT_FLUSH_ASSEMBLY) return(0);
823:
824: if (m) rmax = ailen[0];
825: for (i=1; i<mbs; i++) {
826: /* move each row back by the amount of empty slots (fshift) before it*/
827: fshift += imax[i-1] - ailen[i-1];
828: rmax = PetscMax(rmax,ailen[i]);
829: if (fshift) {
830: ip = aj + ai[i]; ap = aa + bs2*ai[i];
831: N = ailen[i];
832: for (j=0; j<N; j++) {
833: ip[j-fshift] = ip[j];
834: PetscMemcpy(ap+(j-fshift)*bs2,ap+j*bs2,bs2*sizeof(MatScalar));
835: }
836: }
837: ai[i] = ai[i-1] + ailen[i-1];
838: }
839: if (mbs) {
840: fshift += imax[mbs-1] - ailen[mbs-1];
841: ai[mbs] = ai[mbs-1] + ailen[mbs-1];
842: }
843: /* reset ilen and imax for each row */
844: for (i=0; i<mbs; i++) {
845: ailen[i] = imax[i] = ai[i+1] - ai[i];
846: }
847: a->nz = ai[mbs];
848:
849: /* diagonals may have moved, reset it */
850: if (a->diag) {
851: PetscMemcpy(a->diag,ai,mbs*sizeof(PetscInt));
852: }
853: if (fshift && a->nounused == -1) {
854: SETERRQ4(PETSC_ERR_PLIB, "Unused space detected in matrix: %D X %D block size %D, %D unneeded", m, A->cmap->n, A->rmap->bs, fshift*bs2);
855: }
856: PetscInfo5(A,"Matrix size: %D X %D, block size %D; storage space: %D unneeded, %D used\n",m,A->rmap->N,A->rmap->bs,fshift*bs2,a->nz*bs2);
857: PetscInfo1(A,"Number of mallocs during MatSetValues is %D\n",a->reallocs);
858: PetscInfo1(A,"Most nonzeros blocks in any row is %D\n",rmax);
859: a->reallocs = 0;
860: A->info.nz_unneeded = (PetscReal)fshift*bs2;
861: a->idiagvalid = PETSC_FALSE;
863: if (A->cmap->n < 65536 && A->cmap->bs == 1) {
864: if (!a->jshort) {
865: PetscMalloc(a->i[A->rmap->n]*sizeof(unsigned short),&a->jshort);
866: PetscLogObjectMemory(A,a->i[A->rmap->n]*sizeof(unsigned short));
867: for (i=0; i<a->i[A->rmap->n]; i++) a->jshort[i] = a->j[i];
868: A->ops->mult = MatMult_SeqSBAIJ_1_ushort;
869: A->ops->sor = MatSOR_SeqSBAIJ_ushort;
870: a->free_jshort = PETSC_TRUE;
871: }
872: }
873: return(0);
874: }
876: /*
877: This function returns an array of flags which indicate the locations of contiguous
878: blocks that should be zeroed. for eg: if bs = 3 and is = [0,1,2,3,5,6,7,8,9]
879: then the resulting sizes = [3,1,1,3,1] correspondig to sets [(0,1,2),(3),(5),(6,7,8),(9)]
880: Assume: sizes should be long enough to hold all the values.
881: */
884: PetscErrorCode MatZeroRows_SeqSBAIJ_Check_Blocks(PetscInt idx[],PetscInt n,PetscInt bs,PetscInt sizes[], PetscInt *bs_max)
885: {
886: PetscInt i,j,k,row;
887: PetscTruth flg;
888:
890: for (i=0,j=0; i<n; j++) {
891: row = idx[i];
892: if (row%bs!=0) { /* Not the begining of a block */
893: sizes[j] = 1;
894: i++;
895: } else if (i+bs > n) { /* Beginning of a block, but complete block doesn't exist (at idx end) */
896: sizes[j] = 1; /* Also makes sure atleast 'bs' values exist for next else */
897: i++;
898: } else { /* Begining of the block, so check if the complete block exists */
899: flg = PETSC_TRUE;
900: for (k=1; k<bs; k++) {
901: if (row+k != idx[i+k]) { /* break in the block */
902: flg = PETSC_FALSE;
903: break;
904: }
905: }
906: if (flg) { /* No break in the bs */
907: sizes[j] = bs;
908: i+= bs;
909: } else {
910: sizes[j] = 1;
911: i++;
912: }
913: }
914: }
915: *bs_max = j;
916: return(0);
917: }
920: /* Only add/insert a(i,j) with i<=j (blocks).
921: Any a(i,j) with i>j input by user is ingored.
922: */
926: PetscErrorCode MatSetValues_SeqSBAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
927: {
928: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
930: PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,lastcol = -1;
931: PetscInt *imax=a->imax,*ai=a->i,*ailen=a->ilen,roworiented=a->roworiented;
932: PetscInt *aj=a->j,nonew=a->nonew,bs=A->rmap->bs,brow,bcol;
933: PetscInt ridx,cidx,bs2=a->bs2;
934: MatScalar *ap,value,*aa=a->a,*bap;
935:
938: for (k=0; k<m; k++) { /* loop over added rows */
939: row = im[k]; /* row number */
940: brow = row/bs; /* block row number */
941: if (row < 0) continue;
942: #if defined(PETSC_USE_DEBUG)
943: if (row >= A->rmap->N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->N-1);
944: #endif
945: rp = aj + ai[brow]; /*ptr to beginning of column value of the row block*/
946: ap = aa + bs2*ai[brow]; /*ptr to beginning of element value of the row block*/
947: rmax = imax[brow]; /* maximum space allocated for this row */
948: nrow = ailen[brow]; /* actual length of this row */
949: low = 0;
950:
951: for (l=0; l<n; l++) { /* loop over added columns */
952: if (in[l] < 0) continue;
953: #if defined(PETSC_USE_DEBUG)
954: if (in[l] >= A->rmap->N) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->rmap->N-1);
955: #endif
956: col = in[l];
957: bcol = col/bs; /* block col number */
958:
959: if (brow > bcol) {
960: if (a->ignore_ltriangular){
961: continue; /* ignore lower triangular values */
962: } else {
963: SETERRQ(PETSC_ERR_USER,"Lower triangular value cannot be set for sbaij format. Ignoring these values, run with -mat_ignore_lower_triangular or call MatSetOption(mat,MAT_IGNORE_LOWER_TRIANGULAR,PETSC_TRUE)");
964: }
965: }
966:
967: ridx = row % bs; cidx = col % bs; /*row and col index inside the block */
968: if ((brow==bcol && ridx<=cidx) || (brow<bcol)){
969: /* element value a(k,l) */
970: if (roworiented) {
971: value = v[l + k*n];
972: } else {
973: value = v[k + l*m];
974: }
975:
976: /* move pointer bap to a(k,l) quickly and add/insert value */
977: if (col <= lastcol) low = 0; high = nrow;
978: lastcol = col;
979: while (high-low > 7) {
980: t = (low+high)/2;
981: if (rp[t] > bcol) high = t;
982: else low = t;
983: }
984: for (i=low; i<high; i++) {
985: if (rp[i] > bcol) break;
986: if (rp[i] == bcol) {
987: bap = ap + bs2*i + bs*cidx + ridx;
988: if (is == ADD_VALUES) *bap += value;
989: else *bap = value;
990: /* for diag block, add/insert its symmetric element a(cidx,ridx) */
991: if (brow == bcol && ridx < cidx){
992: bap = ap + bs2*i + bs*ridx + cidx;
993: if (is == ADD_VALUES) *bap += value;
994: else *bap = value;
995: }
996: goto noinsert1;
997: }
998: }
999:
1000: if (nonew == 1) goto noinsert1;
1001: if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) in the matrix", row, col);
1002: MatSeqXAIJReallocateAIJ(A,a->mbs,bs2,nrow,brow,bcol,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
1003:
1004: N = nrow++ - 1; high++;
1005: /* shift up all the later entries in this row */
1006: for (ii=N; ii>=i; ii--) {
1007: rp[ii+1] = rp[ii];
1008: PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(MatScalar));
1009: }
1010: if (N>=i) {
1011: PetscMemzero(ap+bs2*i,bs2*sizeof(MatScalar));
1012: }
1013: rp[i] = bcol;
1014: ap[bs2*i + bs*cidx + ridx] = value;
1015: noinsert1:;
1016: low = i;
1017: }
1018: } /* end of loop over added columns */
1019: ailen[brow] = nrow;
1020: } /* end of loop over added rows */
1021: return(0);
1022: }
1026: PetscErrorCode MatICCFactor_SeqSBAIJ(Mat inA,IS row,const MatFactorInfo *info)
1027: {
1028: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)inA->data;
1029: Mat outA;
1031: PetscTruth row_identity;
1032:
1034: if (info->levels != 0) SETERRQ(PETSC_ERR_SUP,"Only levels=0 is supported for in-place icc");
1035: ISIdentity(row,&row_identity);
1036: if (!row_identity) SETERRQ(PETSC_ERR_SUP,"Matrix reordering is not supported");
1037: if (inA->rmap->bs != 1) SETERRQ1(PETSC_ERR_SUP,"Matrix block size %D is not supported",inA->rmap->bs); /* Need to replace MatCholeskyFactorSymbolic_SeqSBAIJ_MSR()! */
1039: outA = inA;
1040: inA->factor = MAT_FACTOR_ICC;
1041:
1042: MatMarkDiagonal_SeqSBAIJ(inA);
1043: MatSeqSBAIJSetNumericFactorization_inplace(inA,row_identity);
1045: PetscObjectReference((PetscObject)row);
1046: if (a->row) { ISDestroy(a->row); }
1047: a->row = row;
1048: PetscObjectReference((PetscObject)row);
1049: if (a->col) { ISDestroy(a->col); }
1050: a->col = row;
1051:
1052: /* Create the invert permutation so that it can be used in MatCholeskyFactorNumeric() */
1053: if (a->icol) {ISInvertPermutation(row,PETSC_DECIDE, &a->icol);}
1054: PetscLogObjectParent(inA,a->icol);
1055:
1056: if (!a->solve_work) {
1057: PetscMalloc((inA->rmap->N+inA->rmap->bs)*sizeof(PetscScalar),&a->solve_work);
1058: PetscLogObjectMemory(inA,(inA->rmap->N+inA->rmap->bs)*sizeof(PetscScalar));
1059: }
1060:
1061: MatCholeskyFactorNumeric(outA,inA,info);
1062: return(0);
1063: }
1068: PetscErrorCode MatSeqSBAIJSetColumnIndices_SeqSBAIJ(Mat mat,PetscInt *indices)
1069: {
1070: Mat_SeqSBAIJ *baij = (Mat_SeqSBAIJ *)mat->data;
1071: PetscInt i,nz,n;
1072:
1074: nz = baij->maxnz;
1075: n = mat->cmap->n;
1076: for (i=0; i<nz; i++) {
1077: baij->j[i] = indices[i];
1078: }
1079: baij->nz = nz;
1080: for (i=0; i<n; i++) {
1081: baij->ilen[i] = baij->imax[i];
1082: }
1083: return(0);
1084: }
1089: /*@
1090: MatSeqSBAIJSetColumnIndices - Set the column indices for all the rows
1091: in the matrix.
1092:
1093: Input Parameters:
1094: + mat - the SeqSBAIJ matrix
1095: - indices - the column indices
1096:
1097: Level: advanced
1098:
1099: Notes:
1100: This can be called if you have precomputed the nonzero structure of the
1101: matrix and want to provide it to the matrix object to improve the performance
1102: of the MatSetValues() operation.
1103:
1104: You MUST have set the correct numbers of nonzeros per row in the call to
1105: MatCreateSeqSBAIJ(), and the columns indices MUST be sorted.
1106:
1107: MUST be called before any calls to MatSetValues()
1108:
1109: .seealso: MatCreateSeqSBAIJ
1110: @*/
1111: PetscErrorCode MatSeqSBAIJSetColumnIndices(Mat mat,PetscInt *indices)
1112: {
1113: PetscErrorCode ierr,(*f)(Mat,PetscInt *);
1114:
1118: PetscObjectQueryFunction((PetscObject)mat,"MatSeqSBAIJSetColumnIndices_C",(void (**)(void))&f);
1119: if (f) {
1120: (*f)(mat,indices);
1121: } else {
1122: SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to set column indices");
1123: }
1124: return(0);
1125: }
1129: PetscErrorCode MatCopy_SeqSBAIJ(Mat A,Mat B,MatStructure str)
1130: {
1134: /* If the two matrices have the same copy implementation, use fast copy. */
1135: if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
1136: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
1137: Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ*)B->data;
1139: if (a->i[A->rmap->N] != b->i[B->rmap->N]) {
1140: SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different");
1141: }
1142: PetscMemcpy(b->a,a->a,(a->i[A->rmap->N])*sizeof(PetscScalar));
1143: } else {
1144: MatGetRowUpperTriangular(A);
1145: MatCopy_Basic(A,B,str);
1146: MatRestoreRowUpperTriangular(A);
1147: }
1148: return(0);
1149: }
1153: PetscErrorCode MatSetUpPreallocation_SeqSBAIJ(Mat A)
1154: {
1156:
1158: MatSeqSBAIJSetPreallocation_SeqSBAIJ(A,-PetscMax(A->rmap->bs,1),PETSC_DEFAULT,0);
1159: return(0);
1160: }
1164: PetscErrorCode MatGetArray_SeqSBAIJ(Mat A,PetscScalar *array[])
1165: {
1166: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
1168: *array = a->a;
1169: return(0);
1170: }
1174: PetscErrorCode MatRestoreArray_SeqSBAIJ(Mat A,PetscScalar *array[])
1175: {
1177: return(0);
1178: }
1182: PetscErrorCode MatAXPY_SeqSBAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
1183: {
1184: Mat_SeqSBAIJ *x=(Mat_SeqSBAIJ *)X->data, *y=(Mat_SeqSBAIJ *)Y->data;
1186: PetscInt i,bs=Y->rmap->bs,bs2,j;
1187: PetscBLASInt one = 1,bnz = PetscBLASIntCast(x->nz);
1188:
1190: if (str == SAME_NONZERO_PATTERN) {
1191: PetscScalar alpha = a;
1192: BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one);
1193: } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
1194: if (y->xtoy && y->XtoY != X) {
1195: PetscFree(y->xtoy);
1196: MatDestroy(y->XtoY);
1197: }
1198: if (!y->xtoy) { /* get xtoy */
1199: MatAXPYGetxtoy_Private(x->mbs,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);
1200: y->XtoY = X;
1201: }
1202: bs2 = bs*bs;
1203: for (i=0; i<x->nz; i++) {
1204: j = 0;
1205: while (j < bs2){
1206: y->a[bs2*y->xtoy[i]+j] += a*(x->a[bs2*i+j]);
1207: j++;
1208: }
1209: }
1210: PetscInfo3(Y,"ratio of nnz_s(X)/nnz_s(Y): %D/%D = %G\n",bs2*x->nz,bs2*y->nz,(PetscReal)(bs2*x->nz)/(bs2*y->nz));
1211: } else {
1212: MatGetRowUpperTriangular(X);
1213: MatAXPY_Basic(Y,a,X,str);
1214: MatRestoreRowUpperTriangular(X);
1215: }
1216: return(0);
1217: }
1221: PetscErrorCode MatSetBlockSize_SeqSBAIJ(Mat A,PetscInt bs)
1222: {
1223: PetscInt rbs,cbs;
1227: PetscLayoutGetBlockSize(A->rmap,&rbs);
1228: PetscLayoutGetBlockSize(A->cmap,&cbs);
1229: if (rbs != bs) SETERRQ2(PETSC_ERR_ARG_SIZ,"Attempt to set block size %d with SBAIJ %d",bs,rbs);
1230: if (cbs != bs) SETERRQ2(PETSC_ERR_ARG_SIZ,"Attempt to set block size %d with SBAIJ %d",bs,cbs);
1231: return(0);
1232: }
1236: PetscErrorCode MatIsSymmetric_SeqSBAIJ(Mat A,PetscReal tol,PetscTruth *flg)
1237: {
1239: *flg = PETSC_TRUE;
1240: return(0);
1241: }
1245: PetscErrorCode MatIsStructurallySymmetric_SeqSBAIJ(Mat A,PetscTruth *flg)
1246: {
1248: *flg = PETSC_TRUE;
1249: return(0);
1250: }
1254: PetscErrorCode MatIsHermitian_SeqSBAIJ(Mat A,PetscReal tol,PetscTruth *flg)
1255: {
1257: *flg = PETSC_FALSE;
1258: return(0);
1259: }
1263: PetscErrorCode MatRealPart_SeqSBAIJ(Mat A)
1264: {
1265: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
1266: PetscInt i,nz = a->bs2*a->i[a->mbs];
1267: MatScalar *aa = a->a;
1270: for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
1271: return(0);
1272: }
1276: PetscErrorCode MatImaginaryPart_SeqSBAIJ(Mat A)
1277: {
1278: Mat_SeqSBAIJ *a = (Mat_SeqSBAIJ*)A->data;
1279: PetscInt i,nz = a->bs2*a->i[a->mbs];
1280: MatScalar *aa = a->a;
1283: for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
1284: return(0);
1285: }
1287: /* -------------------------------------------------------------------*/
1288: static struct _MatOps MatOps_Values = {MatSetValues_SeqSBAIJ,
1289: MatGetRow_SeqSBAIJ,
1290: MatRestoreRow_SeqSBAIJ,
1291: MatMult_SeqSBAIJ_N,
1292: /* 4*/ MatMultAdd_SeqSBAIJ_N,
1293: MatMult_SeqSBAIJ_N, /* transpose versions are same as non-transpose versions */
1294: MatMultAdd_SeqSBAIJ_N,
1295: 0,
1296: 0,
1297: 0,
1298: /*10*/ 0,
1299: 0,
1300: MatCholeskyFactor_SeqSBAIJ,
1301: MatSOR_SeqSBAIJ,
1302: MatTranspose_SeqSBAIJ,
1303: /*15*/ MatGetInfo_SeqSBAIJ,
1304: MatEqual_SeqSBAIJ,
1305: MatGetDiagonal_SeqSBAIJ,
1306: MatDiagonalScale_SeqSBAIJ,
1307: MatNorm_SeqSBAIJ,
1308: /*20*/ 0,
1309: MatAssemblyEnd_SeqSBAIJ,
1310: MatSetOption_SeqSBAIJ,
1311: MatZeroEntries_SeqSBAIJ,
1312: /*24*/ 0,
1313: 0,
1314: 0,
1315: 0,
1316: 0,
1317: /*29*/ MatSetUpPreallocation_SeqSBAIJ,
1318: 0,
1319: 0,
1320: MatGetArray_SeqSBAIJ,
1321: MatRestoreArray_SeqSBAIJ,
1322: /*34*/ MatDuplicate_SeqSBAIJ,
1323: 0,
1324: 0,
1325: 0,
1326: MatICCFactor_SeqSBAIJ,
1327: /*39*/ MatAXPY_SeqSBAIJ,
1328: MatGetSubMatrices_SeqSBAIJ,
1329: MatIncreaseOverlap_SeqSBAIJ,
1330: MatGetValues_SeqSBAIJ,
1331: MatCopy_SeqSBAIJ,
1332: /*44*/ 0,
1333: MatScale_SeqSBAIJ,
1334: 0,
1335: 0,
1336: 0,
1337: /*49*/ MatSetBlockSize_SeqSBAIJ,
1338: MatGetRowIJ_SeqSBAIJ,
1339: MatRestoreRowIJ_SeqSBAIJ,
1340: 0,
1341: 0,
1342: /*54*/ 0,
1343: 0,
1344: 0,
1345: 0,
1346: MatSetValuesBlocked_SeqSBAIJ,
1347: /*59*/ MatGetSubMatrix_SeqSBAIJ,
1348: 0,
1349: 0,
1350: 0,
1351: 0,
1352: /*64*/ 0,
1353: 0,
1354: 0,
1355: 0,
1356: 0,
1357: /*69*/ MatGetRowMaxAbs_SeqSBAIJ,
1358: 0,
1359: 0,
1360: 0,
1361: 0,
1362: /*74*/ 0,
1363: 0,
1364: 0,
1365: 0,
1366: 0,
1367: /*79*/ 0,
1368: 0,
1369: 0,
1370: #if !defined(PETSC_USE_COMPLEX)
1371: MatGetInertia_SeqSBAIJ,
1372: #else
1373: 0,
1374: #endif
1375: MatLoad_SeqSBAIJ,
1376: /*84*/ MatIsSymmetric_SeqSBAIJ,
1377: MatIsHermitian_SeqSBAIJ,
1378: MatIsStructurallySymmetric_SeqSBAIJ,
1379: 0,
1380: 0,
1381: /*89*/ 0,
1382: 0,
1383: 0,
1384: 0,
1385: 0,
1386: /*94*/ 0,
1387: 0,
1388: 0,
1389: 0,
1390: 0,
1391: /*99*/ 0,
1392: 0,
1393: 0,
1394: 0,
1395: 0,
1396: /*104*/0,
1397: MatRealPart_SeqSBAIJ,
1398: MatImaginaryPart_SeqSBAIJ,
1399: MatGetRowUpperTriangular_SeqSBAIJ,
1400: MatRestoreRowUpperTriangular_SeqSBAIJ,
1401: /*109*/0,
1402: 0,
1403: 0,
1404: 0,
1405: MatMissingDiagonal_SeqSBAIJ,
1406: /*114*/0,
1407: 0,
1408: 0,
1409: 0,
1410: 0,
1411: /*119*/0,
1412: 0,
1413: 0
1414: };
1419: PetscErrorCode MatStoreValues_SeqSBAIJ(Mat mat)
1420: {
1421: Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1422: PetscInt nz = aij->i[mat->rmap->N]*mat->rmap->bs*aij->bs2;
1424:
1426: if (aij->nonew != 1) {
1427: SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
1428: }
1429:
1430: /* allocate space for values if not already there */
1431: if (!aij->saved_values) {
1432: PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);
1433: }
1434:
1435: /* copy values over */
1436: PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));
1437: return(0);
1438: }
1444: PetscErrorCode MatRetrieveValues_SeqSBAIJ(Mat mat)
1445: {
1446: Mat_SeqSBAIJ *aij = (Mat_SeqSBAIJ *)mat->data;
1448: PetscInt nz = aij->i[mat->rmap->N]*mat->rmap->bs*aij->bs2;
1449:
1451: if (aij->nonew != 1) {
1452: SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
1453: }
1454: if (!aij->saved_values) {
1455: SETERRQ(PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
1456: }
1457:
1458: /* copy values over */
1459: PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));
1460: return(0);
1461: }
1467: PetscErrorCode MatSeqSBAIJSetPreallocation_SeqSBAIJ(Mat B,PetscInt bs,PetscInt nz,PetscInt *nnz)
1468: {
1469: Mat_SeqSBAIJ *b = (Mat_SeqSBAIJ*)B->data;
1471: PetscInt i,mbs,bs2, newbs = PetscAbs(bs);
1472: PetscTruth skipallocation = PETSC_FALSE,flg = PETSC_FALSE;
1473:
1475: B->preallocated = PETSC_TRUE;
1476: if (bs < 0) {
1477: PetscOptionsBegin(((PetscObject)B)->comm,((PetscObject)B)->prefix,"Options for MPISBAIJ matrix","Mat");
1478: PetscOptionsInt("-mat_block_size","Set the blocksize used to store the matrix","MatSeqSBAIJSetPreallocation",newbs,&newbs,PETSC_NULL);
1479: PetscOptionsEnd();
1480: bs = PetscAbs(bs);
1481: }
1482: if (nnz && newbs != bs) {
1483: SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot change blocksize from command line if setting nnz");
1484: }
1485: bs = newbs;
1487: PetscLayoutSetBlockSize(B->rmap,bs);
1488: PetscLayoutSetBlockSize(B->cmap,bs);
1489: PetscLayoutSetUp(B->rmap);
1490: PetscLayoutSetUp(B->cmap);
1492: mbs = B->rmap->N/bs;
1493: bs2 = bs*bs;
1494:
1495: if (mbs*bs != B->rmap->N) {
1496: SETERRQ(PETSC_ERR_ARG_SIZ,"Number rows, cols must be divisible by blocksize");
1497: }
1498:
1499: if (nz == MAT_SKIP_ALLOCATION) {
1500: skipallocation = PETSC_TRUE;
1501: nz = 0;
1502: }
1504: if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 3;
1505: if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
1506: if (nnz) {
1507: for (i=0; i<mbs; i++) {
1508: if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %D value %D",i,nnz[i]);
1509: if (nnz[i] > mbs) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than block row length: local row %D value %D rowlength %D",i,nnz[i],mbs);
1510: }
1511: }
1512:
1513: B->ops->mult = MatMult_SeqSBAIJ_N;
1514: B->ops->multadd = MatMultAdd_SeqSBAIJ_N;
1515: B->ops->multtranspose = MatMult_SeqSBAIJ_N;
1516: B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_N;
1517: PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_no_unroll",&flg,PETSC_NULL);
1518: if (!flg) {
1519: switch (bs) {
1520: case 1:
1521: B->ops->mult = MatMult_SeqSBAIJ_1;
1522: B->ops->multadd = MatMultAdd_SeqSBAIJ_1;
1523: B->ops->multtranspose = MatMult_SeqSBAIJ_1;
1524: B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_1;
1525: break;
1526: case 2:
1527: B->ops->mult = MatMult_SeqSBAIJ_2;
1528: B->ops->multadd = MatMultAdd_SeqSBAIJ_2;
1529: B->ops->multtranspose = MatMult_SeqSBAIJ_2;
1530: B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_2;
1531: break;
1532: case 3:
1533: B->ops->mult = MatMult_SeqSBAIJ_3;
1534: B->ops->multadd = MatMultAdd_SeqSBAIJ_3;
1535: B->ops->multtranspose = MatMult_SeqSBAIJ_3;
1536: B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_3;
1537: break;
1538: case 4:
1539: B->ops->mult = MatMult_SeqSBAIJ_4;
1540: B->ops->multadd = MatMultAdd_SeqSBAIJ_4;
1541: B->ops->multtranspose = MatMult_SeqSBAIJ_4;
1542: B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_4;
1543: break;
1544: case 5:
1545: B->ops->mult = MatMult_SeqSBAIJ_5;
1546: B->ops->multadd = MatMultAdd_SeqSBAIJ_5;
1547: B->ops->multtranspose = MatMult_SeqSBAIJ_5;
1548: B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_5;
1549: break;
1550: case 6:
1551: B->ops->mult = MatMult_SeqSBAIJ_6;
1552: B->ops->multadd = MatMultAdd_SeqSBAIJ_6;
1553: B->ops->multtranspose = MatMult_SeqSBAIJ_6;
1554: B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_6;
1555: break;
1556: case 7:
1557: B->ops->mult = MatMult_SeqSBAIJ_7;
1558: B->ops->multadd = MatMultAdd_SeqSBAIJ_7;
1559: B->ops->multtranspose = MatMult_SeqSBAIJ_7;
1560: B->ops->multtransposeadd = MatMultAdd_SeqSBAIJ_7;
1561: break;
1562: }
1563: }
1564:
1565: b->mbs = mbs;
1566: b->nbs = mbs;
1567: if (!skipallocation) {
1568: if (!b->imax) {
1569: PetscMalloc2(mbs,PetscInt,&b->imax,mbs,PetscInt,&b->ilen);
1570: b->free_imax_ilen = PETSC_TRUE;
1571: PetscLogObjectMemory(B,2*mbs*sizeof(PetscInt));
1572: }
1573: if (!nnz) {
1574: if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
1575: else if (nz <= 0) nz = 1;
1576: for (i=0; i<mbs; i++) {
1577: b->imax[i] = nz;
1578: }
1579: nz = nz*mbs; /* total nz */
1580: } else {
1581: nz = 0;
1582: for (i=0; i<mbs; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
1583: }
1584: /* b->ilen will count nonzeros in each block row so far. */
1585: for (i=0; i<mbs; i++) { b->ilen[i] = 0;}
1586: /* nz=(nz+mbs)/2; */ /* total diagonal and superdiagonal nonzero blocks */
1587:
1588: /* allocate the matrix space */
1589: MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);
1590: PetscMalloc3(bs2*nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap->N+1,PetscInt,&b->i);
1591: PetscLogObjectMemory(B,(B->rmap->N+1)*sizeof(PetscInt)+nz*(bs2*sizeof(PetscScalar)+sizeof(PetscInt)));
1592: PetscMemzero(b->a,nz*bs2*sizeof(MatScalar));
1593: PetscMemzero(b->j,nz*sizeof(PetscInt));
1594: b->singlemalloc = PETSC_TRUE;
1595:
1596: /* pointer to beginning of each row */
1597: b->i[0] = 0;
1598: for (i=1; i<mbs+1; i++) {
1599: b->i[i] = b->i[i-1] + b->imax[i-1];
1600: }
1601: b->free_a = PETSC_TRUE;
1602: b->free_ij = PETSC_TRUE;
1603: } else {
1604: b->free_a = PETSC_FALSE;
1605: b->free_ij = PETSC_FALSE;
1606: }
1607:
1608: B->rmap->bs = bs;
1609: b->bs2 = bs2;
1610: b->nz = 0;
1611: b->maxnz = nz*bs2;
1612:
1613: b->inew = 0;
1614: b->jnew = 0;
1615: b->anew = 0;
1616: b->a2anew = 0;
1617: b->permute = PETSC_FALSE;
1618: return(0);
1619: }
1622: /*
1623: This is used to set the numeric factorization for both Cholesky and ICC symbolic factorization
1624: */
1627: PetscErrorCode MatSeqSBAIJSetNumericFactorization_inplace(Mat B,PetscTruth natural)
1628: {
1630: PetscTruth flg = PETSC_FALSE;
1631: PetscInt bs = B->rmap->bs;
1634: PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_no_unroll",&flg,PETSC_NULL);
1635: if (flg) bs = 8;
1637: if (!natural) {
1638: switch (bs) {
1639: case 1:
1640: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_inplace;
1641: break;
1642: case 2:
1643: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2;
1644: break;
1645: case 3:
1646: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3;
1647: break;
1648: case 4:
1649: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4;
1650: break;
1651: case 5:
1652: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5;
1653: break;
1654: case 6:
1655: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6;
1656: break;
1657: case 7:
1658: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7;
1659: break;
1660: default:
1661: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N;
1662: break;
1663: }
1664: } else {
1665: switch (bs) {
1666: case 1:
1667: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_1_NaturalOrdering_inplace;
1668: break;
1669: case 2:
1670: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_2_NaturalOrdering;
1671: break;
1672: case 3:
1673: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_3_NaturalOrdering;
1674: break;
1675: case 4:
1676: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_4_NaturalOrdering;
1677: break;
1678: case 5:
1679: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_5_NaturalOrdering;
1680: break;
1681: case 6:
1682: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_6_NaturalOrdering;
1683: break;
1684: case 7:
1685: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_7_NaturalOrdering;
1686: break;
1687: default:
1688: B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqSBAIJ_N_NaturalOrdering;
1689: break;
1690: }
1691: }
1692: return(0);
1693: }
1696: EXTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqAIJ(Mat, MatType,MatReuse,Mat*);
1697: EXTERN PetscErrorCode MatConvert_SeqSBAIJ_SeqBAIJ(Mat, MatType,MatReuse,Mat*);
1700:
1704: PetscErrorCode MatGetFactor_seqsbaij_petsc(Mat A,MatFactorType ftype,Mat *B)
1705: {
1706: PetscInt n = A->rmap->n;
1707: PetscErrorCode ierr;
1710: MatCreate(((PetscObject)A)->comm,B);
1711: MatSetSizes(*B,n,n,n,n);
1712: if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1713: MatSetType(*B,MATSEQSBAIJ);
1714: MatSeqSBAIJSetPreallocation(*B,1,MAT_SKIP_ALLOCATION,PETSC_NULL);
1715: (*B)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqSBAIJ;
1716: (*B)->ops->iccfactorsymbolic = MatICCFactorSymbolic_SeqSBAIJ;
1717: } else SETERRQ(PETSC_ERR_SUP,"Factor type not supported");
1718: (*B)->factor = ftype;
1719: return(0);
1720: }
1726: PetscErrorCode MatGetFactorAvailable_seqsbaij_petsc(Mat A,MatFactorType ftype,PetscTruth *flg)
1727: {
1729: if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1730: *flg = PETSC_TRUE;
1731: } else {
1732: *flg = PETSC_FALSE;
1733: }
1734: return(0);
1735: }
1739: #if defined(PETSC_HAVE_MUMPS)
1741: #endif
1742: #if defined(PETSC_HAVE_SPOOLES)
1744: #endif
1745: #if defined(PETSC_HAVE_PASTIX)
1747: #endif
1750: /*MC
1751: MATSEQSBAIJ - MATSEQSBAIJ = "seqsbaij" - A matrix type to be used for sequential symmetric block sparse matrices,
1752: based on block compressed sparse row format. Only the upper triangular portion of the matrix is stored.
1753:
1754: Options Database Keys:
1755: . -mat_type seqsbaij - sets the matrix type to "seqsbaij" during a call to MatSetFromOptions()
1756:
1757: Level: beginner
1758:
1759: .seealso: MatCreateSeqSBAIJ
1760: M*/
1765: PetscErrorCode MatCreate_SeqSBAIJ(Mat B)
1766: {
1767: Mat_SeqSBAIJ *b;
1769: PetscMPIInt size;
1770: PetscTruth no_unroll = PETSC_FALSE,no_inode = PETSC_FALSE;
1773: MPI_Comm_size(((PetscObject)B)->comm,&size);
1774: if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"Comm must be of size 1");
1775:
1776: PetscNewLog(B,Mat_SeqSBAIJ,&b);
1777: B->data = (void*)b;
1778: PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));
1779: B->ops->destroy = MatDestroy_SeqSBAIJ;
1780: B->ops->view = MatView_SeqSBAIJ;
1781: B->mapping = 0;
1782: b->row = 0;
1783: b->icol = 0;
1784: b->reallocs = 0;
1785: b->saved_values = 0;
1786: b->inode.limit = 5;
1787: b->inode.max_limit = 5;
1788:
1789: b->roworiented = PETSC_TRUE;
1790: b->nonew = 0;
1791: b->diag = 0;
1792: b->solve_work = 0;
1793: b->mult_work = 0;
1794: B->spptr = 0;
1795: b->keepnonzeropattern = PETSC_FALSE;
1796: b->xtoy = 0;
1797: b->XtoY = 0;
1798:
1799: b->inew = 0;
1800: b->jnew = 0;
1801: b->anew = 0;
1802: b->a2anew = 0;
1803: b->permute = PETSC_FALSE;
1805: b->ignore_ltriangular = PETSC_FALSE;
1806: PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_ignore_lower_triangular",&b->ignore_ltriangular,PETSC_NULL);
1808: b->getrow_utriangular = PETSC_FALSE;
1809: PetscOptionsGetTruth(((PetscObject)B)->prefix,"-mat_getrow_uppertriangular",&b->getrow_utriangular,PETSC_NULL);
1811: #if defined(PETSC_HAVE_PASTIX)
1812: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_pastix_C",
1813: "MatGetFactor_seqsbaij_pastix",
1814: MatGetFactor_seqsbaij_pastix);
1815: #endif
1816: #if defined(PETSC_HAVE_SPOOLES)
1817: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_spooles_C",
1818: "MatGetFactor_seqsbaij_spooles",
1819: MatGetFactor_seqsbaij_spooles);
1820: #endif
1821: #if defined(PETSC_HAVE_MUMPS)
1822: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_mumps_C",
1823: "MatGetFactor_seqsbaij_mumps",
1824: MatGetFactor_seqsbaij_mumps);
1825: #endif
1826: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_petsc_C",
1827: "MatGetFactorAvailable_seqsbaij_petsc",
1828: MatGetFactorAvailable_seqsbaij_petsc);
1829: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_petsc_C",
1830: "MatGetFactor_seqsbaij_petsc",
1831: MatGetFactor_seqsbaij_petsc);
1832: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
1833: "MatStoreValues_SeqSBAIJ",
1834: MatStoreValues_SeqSBAIJ);
1835: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
1836: "MatRetrieveValues_SeqSBAIJ",
1837: (void*)MatRetrieveValues_SeqSBAIJ);
1838: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetColumnIndices_C",
1839: "MatSeqSBAIJSetColumnIndices_SeqSBAIJ",
1840: MatSeqSBAIJSetColumnIndices_SeqSBAIJ);
1841: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqaij_C",
1842: "MatConvert_SeqSBAIJ_SeqAIJ",
1843: MatConvert_SeqSBAIJ_SeqAIJ);
1844: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_seqbaij_C",
1845: "MatConvert_SeqSBAIJ_SeqBAIJ",
1846: MatConvert_SeqSBAIJ_SeqBAIJ);
1847: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqSBAIJSetPreallocation_C",
1848: "MatSeqSBAIJSetPreallocation_SeqSBAIJ",
1849: MatSeqSBAIJSetPreallocation_SeqSBAIJ);
1851: B->symmetric = PETSC_TRUE;
1852: B->structurally_symmetric = PETSC_TRUE;
1853: B->symmetric_set = PETSC_TRUE;
1854: B->structurally_symmetric_set = PETSC_TRUE;
1855: PetscObjectChangeTypeName((PetscObject)B,MATSEQSBAIJ);
1857: PetscOptionsBegin(((PetscObject)B)->comm,((PetscObject)B)->prefix,"Options for SEQSBAIJ matrix","Mat");
1858: PetscOptionsTruth("-mat_no_unroll","Do not optimize for inodes (slower)",PETSC_NULL,no_unroll,&no_unroll,PETSC_NULL);
1859: if (no_unroll) {PetscInfo(B,"Not using Inode routines due to -mat_no_unroll\n");}
1860: PetscOptionsTruth("-mat_no_inode","Do not optimize for inodes (slower)",PETSC_NULL,no_inode,&no_inode,PETSC_NULL);
1861: if (no_inode) {PetscInfo(B,"Not using Inode routines due to -mat_no_inode\n");}
1862: PetscOptionsInt("-mat_inode_limit","Do not use inodes larger then this value",PETSC_NULL,b->inode.limit,&b->inode.limit,PETSC_NULL);
1863: PetscOptionsEnd();
1864: b->inode.use = (PetscTruth)(!(no_unroll || no_inode));
1865: if (b->inode.limit > b->inode.max_limit) b->inode.limit = b->inode.max_limit;
1867: return(0);
1868: }
1873: /*@C
1874: MatSeqSBAIJSetPreallocation - Creates a sparse symmetric matrix in block AIJ (block
1875: compressed row) format. For good matrix assembly performance the
1876: user should preallocate the matrix storage by setting the parameter nz
1877: (or the array nnz). By setting these parameters accurately, performance
1878: during matrix assembly can be increased by more than a factor of 50.
1880: Collective on Mat
1882: Input Parameters:
1883: + A - the symmetric matrix
1884: . bs - size of block
1885: . nz - number of block nonzeros per block row (same for all rows)
1886: - nnz - array containing the number of block nonzeros in the upper triangular plus
1887: diagonal portion of each block (possibly different for each block row) or PETSC_NULL
1889: Options Database Keys:
1890: . -mat_no_unroll - uses code that does not unroll the loops in the
1891: block calculations (much slower)
1892: . -mat_block_size - size of the blocks to use (only works if a negative bs is passed in
1894: Level: intermediate
1896: Notes:
1897: Specify the preallocated storage with either nz or nnz (not both).
1898: Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
1899: allocation. For additional details, see the users manual chapter on
1900: matrices.
1902: You can call MatGetInfo() to get information on how effective the preallocation was;
1903: for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
1904: You can also run with the option -info and look for messages with the string
1905: malloc in them to see if additional memory allocation was needed.
1907: If the nnz parameter is given then the nz parameter is ignored
1910: .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ()
1911: @*/
1912: PetscErrorCode MatSeqSBAIJSetPreallocation(Mat B,PetscInt bs,PetscInt nz,const PetscInt nnz[])
1913: {
1914: PetscErrorCode ierr,(*f)(Mat,PetscInt,PetscInt,const PetscInt[]);
1917: PetscObjectQueryFunction((PetscObject)B,"MatSeqSBAIJSetPreallocation_C",(void (**)(void))&f);
1918: if (f) {
1919: (*f)(B,bs,nz,nnz);
1920: }
1921: return(0);
1922: }
1926: /*@C
1927: MatCreateSeqSBAIJ - Creates a sparse symmetric matrix in block AIJ (block
1928: compressed row) format. For good matrix assembly performance the
1929: user should preallocate the matrix storage by setting the parameter nz
1930: (or the array nnz). By setting these parameters accurately, performance
1931: during matrix assembly can be increased by more than a factor of 50.
1933: Collective on MPI_Comm
1935: Input Parameters:
1936: + comm - MPI communicator, set to PETSC_COMM_SELF
1937: . bs - size of block
1938: . m - number of rows, or number of columns
1939: . nz - number of block nonzeros per block row (same for all rows)
1940: - nnz - array containing the number of block nonzeros in the upper triangular plus
1941: diagonal portion of each block (possibly different for each block row) or PETSC_NULL
1943: Output Parameter:
1944: . A - the symmetric matrix
1946: Options Database Keys:
1947: . -mat_no_unroll - uses code that does not unroll the loops in the
1948: block calculations (much slower)
1949: . -mat_block_size - size of the blocks to use
1951: Level: intermediate
1953: It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
1954: MatXXXXSetPreallocation() paradgm instead of this routine directly.
1955: [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
1957: Notes:
1958: The number of rows and columns must be divisible by blocksize.
1959: This matrix type does not support complex Hermitian operation.
1961: Specify the preallocated storage with either nz or nnz (not both).
1962: Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
1963: allocation. For additional details, see the users manual chapter on
1964: matrices.
1966: If the nnz parameter is given then the nz parameter is ignored
1968: .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateMPISBAIJ()
1969: @*/
1970: PetscErrorCode MatCreateSeqSBAIJ(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
1971: {
1973:
1975: MatCreate(comm,A);
1976: MatSetSizes(*A,m,n,m,n);
1977: MatSetType(*A,MATSEQSBAIJ);
1978: MatSeqSBAIJSetPreallocation_SeqSBAIJ(*A,bs,nz,(PetscInt*)nnz);
1979: return(0);
1980: }
1984: PetscErrorCode MatDuplicate_SeqSBAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
1985: {
1986: Mat C;
1987: Mat_SeqSBAIJ *c,*a = (Mat_SeqSBAIJ*)A->data;
1989: PetscInt i,mbs = a->mbs,nz = a->nz,bs2 =a->bs2;
1992: if (a->i[mbs] != nz) SETERRQ(PETSC_ERR_PLIB,"Corrupt matrix");
1994: *B = 0;
1995: MatCreate(((PetscObject)A)->comm,&C);
1996: MatSetSizes(C,A->rmap->N,A->cmap->n,A->rmap->N,A->cmap->n);
1997: MatSetType(C,((PetscObject)A)->type_name);
1998: PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));
1999: c = (Mat_SeqSBAIJ*)C->data;
2001: C->preallocated = PETSC_TRUE;
2002: C->factor = A->factor;
2003: c->row = 0;
2004: c->icol = 0;
2005: c->saved_values = 0;
2006: c->keepnonzeropattern = a->keepnonzeropattern;
2007: C->assembled = PETSC_TRUE;
2009: PetscLayoutCopy(A->rmap,&C->rmap);
2010: PetscLayoutCopy(A->cmap,&C->cmap);
2011: c->bs2 = a->bs2;
2012: c->mbs = a->mbs;
2013: c->nbs = a->nbs;
2015: if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2016: c->imax = a->imax;
2017: c->ilen = a->ilen;
2018: c->free_imax_ilen = PETSC_FALSE;
2019: } else {
2020: PetscMalloc2((mbs+1),PetscInt,&c->imax,(mbs+1),PetscInt,&c->ilen);
2021: PetscLogObjectMemory(C,2*(mbs+1)*sizeof(PetscInt));
2022: for (i=0; i<mbs; i++) {
2023: c->imax[i] = a->imax[i];
2024: c->ilen[i] = a->ilen[i];
2025: }
2026: c->free_imax_ilen = PETSC_TRUE;
2027: }
2029: /* allocate the matrix space */
2030: if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2031: PetscMalloc(bs2*nz*sizeof(MatScalar),&c->a);
2032: PetscLogObjectMemory(C,nz*bs2*sizeof(MatScalar));
2033: c->singlemalloc = PETSC_FALSE;
2034: c->free_ij = PETSC_FALSE;
2035: c->parent = A;
2036: PetscObjectReference((PetscObject)A);
2037: MatSetOption(A,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);
2038: MatSetOption(C,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);
2039: } else {
2040: PetscMalloc3(bs2*nz,MatScalar,&c->a,nz,PetscInt,&c->j,mbs+1,PetscInt,&c->i);
2041: PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(PetscInt));
2042: PetscLogObjectMemory(C,(mbs+1)*sizeof(PetscInt) + nz*(bs2*sizeof(MatScalar) + sizeof(PetscInt)));
2043: c->singlemalloc = PETSC_TRUE;
2044: c->free_ij = PETSC_TRUE;
2045: }
2046: if (mbs > 0) {
2047: if (cpvalues != MAT_SHARE_NONZERO_PATTERN) {
2048: PetscMemcpy(c->j,a->j,nz*sizeof(PetscInt));
2049: }
2050: if (cpvalues == MAT_COPY_VALUES) {
2051: PetscMemcpy(c->a,a->a,bs2*nz*sizeof(MatScalar));
2052: } else {
2053: PetscMemzero(c->a,bs2*nz*sizeof(MatScalar));
2054: }
2055: if (a->jshort) {
2056: if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2057: c->jshort = a->jshort;
2058: c->free_jshort = PETSC_FALSE;
2059: } else {
2060: PetscMalloc(nz*sizeof(unsigned short),&c->jshort);
2061: PetscLogObjectMemory(C,nz*sizeof(unsigned short));
2062: PetscMemcpy(c->jshort,a->jshort,nz*sizeof(unsigned short));
2063: c->free_jshort = PETSC_TRUE;
2064: }
2065: }
2066: }
2068: c->roworiented = a->roworiented;
2069: c->nonew = a->nonew;
2071: if (a->diag) {
2072: if (cpvalues == MAT_SHARE_NONZERO_PATTERN) {
2073: c->diag = a->diag;
2074: c->free_diag = PETSC_FALSE;
2075: } else {
2076: PetscMalloc(mbs*sizeof(PetscInt),&c->diag);
2077: PetscLogObjectMemory(C,mbs*sizeof(PetscInt));
2078: for (i=0; i<mbs; i++) {
2079: c->diag[i] = a->diag[i];
2080: }
2081: c->free_diag = PETSC_TRUE;
2082: }
2083: } else c->diag = 0;
2084: c->nz = a->nz;
2085: c->maxnz = a->maxnz;
2086: c->solve_work = 0;
2087: c->mult_work = 0;
2088: c->free_a = PETSC_TRUE;
2089: *B = C;
2090: PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);
2091: return(0);
2092: }
2096: PetscErrorCode MatLoad_SeqSBAIJ(PetscViewer viewer, const MatType type,Mat *A)
2097: {
2098: Mat_SeqSBAIJ *a;
2099: Mat B;
2101: int fd;
2102: PetscMPIInt size;
2103: PetscInt i,nz,header[4],*rowlengths=0,M,N,bs=1;
2104: PetscInt *mask,mbs,*jj,j,rowcount,nzcount,k,*s_browlengths,maskcount;
2105: PetscInt kmax,jcount,block,idx,point,nzcountb,extra_rows;
2106: PetscInt *masked,nmask,tmp,bs2,ishift;
2107: PetscScalar *aa;
2108: MPI_Comm comm = ((PetscObject)viewer)->comm;
2111: PetscOptionsGetInt(PETSC_NULL,"-matload_block_size",&bs,PETSC_NULL);
2112: bs2 = bs*bs;
2114: MPI_Comm_size(comm,&size);
2115: if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"view must have one processor");
2116: PetscViewerBinaryGetDescriptor(viewer,&fd);
2117: PetscBinaryRead(fd,header,4,PETSC_INT);
2118: if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not Mat object");
2119: M = header[1]; N = header[2]; nz = header[3];
2121: if (header[3] < 0) {
2122: SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format, cannot load as SeqSBAIJ");
2123: }
2125: if (M != N) SETERRQ(PETSC_ERR_SUP,"Can only do square matrices");
2127: /*
2128: This code adds extra rows to make sure the number of rows is
2129: divisible by the blocksize
2130: */
2131: mbs = M/bs;
2132: extra_rows = bs - M + bs*(mbs);
2133: if (extra_rows == bs) extra_rows = 0;
2134: else mbs++;
2135: if (extra_rows) {
2136: PetscInfo(viewer,"Padding loaded matrix to match blocksize\n");
2137: }
2139: /* read in row lengths */
2140: PetscMalloc((M+extra_rows)*sizeof(PetscInt),&rowlengths);
2141: PetscBinaryRead(fd,rowlengths,M,PETSC_INT);
2142: for (i=0; i<extra_rows; i++) rowlengths[M+i] = 1;
2144: /* read in column indices */
2145: PetscMalloc((nz+extra_rows)*sizeof(PetscInt),&jj);
2146: PetscBinaryRead(fd,jj,nz,PETSC_INT);
2147: for (i=0; i<extra_rows; i++) jj[nz+i] = M+i;
2149: /* loop over row lengths determining block row lengths */
2150: PetscMalloc(mbs*sizeof(PetscInt),&s_browlengths);
2151: PetscMemzero(s_browlengths,mbs*sizeof(PetscInt));
2152: PetscMalloc2(mbs,PetscInt,&mask,mbs,PetscInt,&masked);
2153: PetscMemzero(mask,mbs*sizeof(PetscInt));
2154: rowcount = 0;
2155: nzcount = 0;
2156: for (i=0; i<mbs; i++) {
2157: nmask = 0;
2158: for (j=0; j<bs; j++) {
2159: kmax = rowlengths[rowcount];
2160: for (k=0; k<kmax; k++) {
2161: tmp = jj[nzcount++]/bs; /* block col. index */
2162: if (!mask[tmp] && tmp >= i) {masked[nmask++] = tmp; mask[tmp] = 1;}
2163: }
2164: rowcount++;
2165: }
2166: s_browlengths[i] += nmask;
2167:
2168: /* zero out the mask elements we set */
2169: for (j=0; j<nmask; j++) mask[masked[j]] = 0;
2170: }
2172: /* create our matrix */
2173: MatCreate(comm,&B);
2174: MatSetSizes(B,M+extra_rows,N+extra_rows,M+extra_rows,N+extra_rows);
2175: MatSetType(B,type);
2176: MatSeqSBAIJSetPreallocation_SeqSBAIJ(B,bs,0,s_browlengths);
2177: a = (Mat_SeqSBAIJ*)B->data;
2179: /* set matrix "i" values */
2180: a->i[0] = 0;
2181: for (i=1; i<= mbs; i++) {
2182: a->i[i] = a->i[i-1] + s_browlengths[i-1];
2183: a->ilen[i-1] = s_browlengths[i-1];
2184: }
2185: a->nz = a->i[mbs];
2187: /* read in nonzero values */
2188: PetscMalloc((nz+extra_rows)*sizeof(PetscScalar),&aa);
2189: PetscBinaryRead(fd,aa,nz,PETSC_SCALAR);
2190: for (i=0; i<extra_rows; i++) aa[nz+i] = 1.0;
2192: /* set "a" and "j" values into matrix */
2193: nzcount = 0; jcount = 0;
2194: for (i=0; i<mbs; i++) {
2195: nzcountb = nzcount;
2196: nmask = 0;
2197: for (j=0; j<bs; j++) {
2198: kmax = rowlengths[i*bs+j];
2199: for (k=0; k<kmax; k++) {
2200: tmp = jj[nzcount++]/bs; /* block col. index */
2201: if (!mask[tmp] && tmp >= i) { masked[nmask++] = tmp; mask[tmp] = 1;}
2202: }
2203: }
2204: /* sort the masked values */
2205: PetscSortInt(nmask,masked);
2207: /* set "j" values into matrix */
2208: maskcount = 1;
2209: for (j=0; j<nmask; j++) {
2210: a->j[jcount++] = masked[j];
2211: mask[masked[j]] = maskcount++;
2212: }
2214: /* set "a" values into matrix */
2215: ishift = bs2*a->i[i];
2216: for (j=0; j<bs; j++) {
2217: kmax = rowlengths[i*bs+j];
2218: for (k=0; k<kmax; k++) {
2219: tmp = jj[nzcountb]/bs ; /* block col. index */
2220: if (tmp >= i){
2221: block = mask[tmp] - 1;
2222: point = jj[nzcountb] - bs*tmp;
2223: idx = ishift + bs2*block + j + bs*point;
2224: a->a[idx] = aa[nzcountb];
2225: }
2226: nzcountb++;
2227: }
2228: }
2229: /* zero out the mask elements we set */
2230: for (j=0; j<nmask; j++) mask[masked[j]] = 0;
2231: }
2232: if (jcount != a->nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Bad binary matrix");
2234: PetscFree(rowlengths);
2235: PetscFree(s_browlengths);
2236: PetscFree(aa);
2237: PetscFree(jj);
2238: PetscFree2(mask,masked);
2240: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
2241: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
2242: MatView_Private(B);
2243: *A = B;
2244: return(0);
2245: }
2249: /*@
2250: MatCreateSeqSBAIJWithArrays - Creates an sequential SBAIJ matrix using matrix elements
2251: (upper triangular entries in CSR format) provided by the user.
2253: Collective on MPI_Comm
2255: Input Parameters:
2256: + comm - must be an MPI communicator of size 1
2257: . bs - size of block
2258: . m - number of rows
2259: . n - number of columns
2260: . i - row indices
2261: . j - column indices
2262: - a - matrix values
2264: Output Parameter:
2265: . mat - the matrix
2267: Level: intermediate
2269: Notes:
2270: The i, j, and a arrays are not copied by this routine, the user must free these arrays
2271: once the matrix is destroyed
2273: You cannot set new nonzero locations into this matrix, that will generate an error.
2275: The i and j indices are 0 based
2277: .seealso: MatCreate(), MatCreateMPISBAIJ(), MatCreateSeqSBAIJ()
2279: @*/
2280: PetscErrorCode MatCreateSeqSBAIJWithArrays(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat)
2281: {
2283: PetscInt ii;
2284: Mat_SeqSBAIJ *sbaij;
2287: if (bs != 1) SETERRQ1(PETSC_ERR_SUP,"block size %D > 1 is not supported yet",bs);
2288: if (i[0]) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
2289:
2290: MatCreate(comm,mat);
2291: MatSetSizes(*mat,m,n,m,n);
2292: MatSetType(*mat,MATSEQSBAIJ);
2293: MatSeqSBAIJSetPreallocation_SeqSBAIJ(*mat,bs,MAT_SKIP_ALLOCATION,0);
2294: sbaij = (Mat_SeqSBAIJ*)(*mat)->data;
2295: PetscMalloc2(m,PetscInt,&sbaij->imax,m,PetscInt,&sbaij->ilen);
2296: PetscLogObjectMemory(*mat,2*m*sizeof(PetscInt));
2298: sbaij->i = i;
2299: sbaij->j = j;
2300: sbaij->a = a;
2301: sbaij->singlemalloc = PETSC_FALSE;
2302: sbaij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2303: sbaij->free_a = PETSC_FALSE;
2304: sbaij->free_ij = PETSC_FALSE;
2306: for (ii=0; ii<m; ii++) {
2307: sbaij->ilen[ii] = sbaij->imax[ii] = i[ii+1] - i[ii];
2308: #if defined(PETSC_USE_DEBUG)
2309: 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]);
2310: #endif
2311: }
2312: #if defined(PETSC_USE_DEBUG)
2313: for (ii=0; ii<sbaij->i[m]; ii++) {
2314: if (j[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]);
2315: if (j[ii] > n - 1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]);
2316: }
2317: #endif
2319: MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
2320: MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
2321: return(0);
2322: }