Actual source code: mhyp.c
1: #define PETSCMAT_DLL
3: /*
4: Creates hypre ijmatrix from PETSc matrix
5: */
7: #include private/matimpl.h
8: #if defined(PETSC_HAVE_HYPRE)
10: #include "HYPRE.h"
11: #include "HYPRE_parcsr_ls.h"
16: PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o,HYPRE_IJMatrix ij)
17: {
19: PetscInt i;
20: PetscInt n_d,*ia_d,n_o,*ia_o;
21: PetscTruth done_d=PETSC_FALSE,done_o=PETSC_FALSE;
22: PetscInt *nnz_d=PETSC_NULL,*nnz_o=PETSC_NULL;
23:
25: if (A_d) { /* determine number of nonzero entries in local diagonal part */
26: MatGetRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,&n_d,&ia_d,PETSC_NULL,&done_d);
27: if (done_d) {
28: PetscMalloc(n_d*sizeof(PetscInt),&nnz_d);
29: for (i=0; i<n_d; i++) {
30: nnz_d[i] = ia_d[i+1] - ia_d[i];
31: }
32: }
33: MatRestoreRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,&n_d,&ia_d,PETSC_NULL,&done_d);
34: }
35: if (A_o) { /* determine number of nonzero entries in local off-diagonal part */
36: MatGetRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,PETSC_NULL,&done_o);
37: if (done_o) {
38: PetscMalloc(n_o*sizeof(PetscInt),&nnz_o);
39: for (i=0; i<n_o; i++) {
40: nnz_o[i] = ia_o[i+1] - ia_o[i];
41: }
42: }
43: MatRestoreRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,PETSC_NULL,&done_o);
44: }
45: if (done_d) { /* set number of nonzeros in HYPRE IJ matrix */
46: if (!done_o) { /* only diagonal part */
47: PetscMalloc(n_d*sizeof(PetscInt),&nnz_o);
48: for (i=0; i<n_d; i++) {
49: nnz_o[i] = 0;
50: }
51: }
52: HYPRE_IJMatrixSetDiagOffdSizes(ij,nnz_d,nnz_o);
53: PetscFree(nnz_d);
54: PetscFree(nnz_o);
55: }
56: return(0);
57: }
62: PetscErrorCode MatHYPRE_IJMatrixCreate(Mat A,HYPRE_IJMatrix *ij)
63: {
65: int rstart,rend,cstart,cend;
66:
71: MatPreallocated(A);
72: rstart = A->rmap->rstart;
73: rend = A->rmap->rend;
74: cstart = A->cmap->rstart;
75: cend = A->cmap->rend;
76: HYPRE_IJMatrixCreate(((PetscObject)A)->comm,rstart,rend-1,cstart,cend-1,ij);
77: HYPRE_IJMatrixSetObjectType(*ij,HYPRE_PARCSR);
78: {
79: PetscTruth same;
80: Mat A_d,A_o;
81: PetscInt *colmap;
82: PetscTypeCompare((PetscObject)A,MATMPIAIJ,&same);
83: if (same) {
84: MatMPIAIJGetSeqAIJ(A,&A_d,&A_o,&colmap);
85: MatHYPRE_IJMatrixPreallocate(A_d,A_o,*ij);
86: return(0);
87: }
88: PetscTypeCompare((PetscObject)A,MATMPIBAIJ,&same);
89: if (same) {
90: MatMPIBAIJGetSeqBAIJ(A,&A_d,&A_o,&colmap);
91: MatHYPRE_IJMatrixPreallocate(A_d,A_o,*ij);
92: return(0);
93: }
94: PetscTypeCompare((PetscObject)A,MATSEQAIJ,&same);
95: if (same) {
96: MatHYPRE_IJMatrixPreallocate(A,PETSC_NULL,*ij);
97: return(0);
98: }
99: PetscTypeCompare((PetscObject)A,MATSEQBAIJ,&same);
100: if (same) {
101: MatHYPRE_IJMatrixPreallocate(A,PETSC_NULL,*ij);
102: return(0);
103: }
104: }
105: return(0);
106: }
110: /*
111: Copies the data over (column indices, numerical values) to hypre matrix
112: */
116: PetscErrorCode MatHYPRE_IJMatrixCopy(Mat A,HYPRE_IJMatrix ij)
117: {
118: PetscErrorCode ierr;
119: PetscInt i,rstart,rend,ncols;
120: const PetscScalar *values;
121: const PetscInt *cols;
122: PetscTruth flg;
125: PetscTypeCompare((PetscObject)A,MATMPIAIJ,&flg);
126: if (flg) {
127: MatHYPRE_IJMatrixFastCopy_MPIAIJ(A,ij);
128: return(0);
129: }
130: PetscTypeCompare((PetscObject)A,MATSEQAIJ,&flg);
131: if (flg) {
132: MatHYPRE_IJMatrixFastCopy_SeqAIJ(A,ij);
133: return(0);
134: }
136: PetscLogEventBegin(MAT_Convert,A,0,0,0);
137: HYPRE_IJMatrixInitialize(ij);
138: MatGetOwnershipRange(A,&rstart,&rend);
139: for (i=rstart; i<rend; i++) {
140: MatGetRow(A,i,&ncols,&cols,&values);
141: HYPRE_IJMatrixSetValues(ij,1,&ncols,&i,cols,values);
142: MatRestoreRow(A,i,&ncols,&cols,&values);
143: }
144: HYPRE_IJMatrixAssemble(ij);
145: PetscLogEventEnd(MAT_Convert,A,0,0,0);
146: return(0);
147: }
149: /*
150: This copies the CSR format directly from the PETSc data structure to the hypre
151: data structure without calls to MatGetRow() or hypre's set values.
153: */
154: #include "_hypre_IJ_mv.h"
155: #include "HYPRE_IJ_mv.h"
156: #include ../src/mat/impls/aij/mpi/mpiaij.h
160: PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat A,HYPRE_IJMatrix ij)
161: {
162: PetscErrorCode ierr;
163: Mat_SeqAIJ *pdiag = (Mat_SeqAIJ*)A->data;;
165: hypre_ParCSRMatrix *par_matrix;
166: hypre_AuxParCSRMatrix *aux_matrix;
167: hypre_CSRMatrix *hdiag,*hoffd;
174: PetscLogEventBegin(MAT_Convert,A,0,0,0);
175: HYPRE_IJMatrixInitialize(ij);
176: par_matrix = (hypre_ParCSRMatrix*)hypre_IJMatrixObject(ij);
177: aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
178: hdiag = hypre_ParCSRMatrixDiag(par_matrix);
179: hoffd = hypre_ParCSRMatrixOffd(par_matrix);
181: /*
182: this is the Hack part where we monkey directly with the hypre datastructures
183: */
185: PetscMemcpy(hdiag->i,pdiag->i,(A->rmap->n + 1)*sizeof(PetscInt));
186: PetscMemcpy(hdiag->j,pdiag->j,pdiag->nz*sizeof(PetscInt));
187: PetscMemcpy(hdiag->data,pdiag->a,pdiag->nz*sizeof(PetscScalar));
189: hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
190: HYPRE_IJMatrixAssemble(ij);
191: PetscLogEventEnd(MAT_Convert,A,0,0,0);
192: return(0);
193: }
197: PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat A,HYPRE_IJMatrix ij)
198: {
199: PetscErrorCode ierr;
200: Mat_MPIAIJ *pA = (Mat_MPIAIJ*)A->data;
201: Mat_SeqAIJ *pdiag,*poffd;
202: PetscInt i,*garray = pA->garray,*jj,cstart,*pjj;
204: hypre_ParCSRMatrix *par_matrix;
205: hypre_AuxParCSRMatrix *aux_matrix;
206: hypre_CSRMatrix *hdiag,*hoffd;
212: pdiag = (Mat_SeqAIJ*) pA->A->data;
213: poffd = (Mat_SeqAIJ*) pA->B->data;
214: /* cstart is only valid for square MPIAIJ layed out in the usual way */
215: MatGetOwnershipRange(A,&cstart,PETSC_NULL);
217: PetscLogEventBegin(MAT_Convert,A,0,0,0);
219: HYPRE_IJMatrixInitialize(ij);
220: par_matrix = (hypre_ParCSRMatrix*)hypre_IJMatrixObject(ij);
221: aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
222: hdiag = hypre_ParCSRMatrixDiag(par_matrix);
223: hoffd = hypre_ParCSRMatrixOffd(par_matrix);
225: /*
226: this is the Hack part where we monkey directly with the hypre datastructures
227: */
229: PetscMemcpy(hdiag->i,pdiag->i,(pA->A->rmap->n + 1)*sizeof(PetscInt));
230: /* need to shift the diag column indices (hdiag->j) back to global numbering since hypre is expecting this */
231: jj = hdiag->j;
232: pjj = pdiag->j;
233: for (i=0; i<pdiag->nz; i++) {
234: jj[i] = cstart + pjj[i];
235: }
236: PetscMemcpy(hdiag->data,pdiag->a,pdiag->nz*sizeof(PetscScalar));
238: PetscMemcpy(hoffd->i,poffd->i,(pA->A->rmap->n + 1)*sizeof(PetscInt));
239: /* need to move the offd column indices (hoffd->j) back to global numbering since hypre is expecting this
240: If we hacked a hypre a bit more we might be able to avoid this step */
241: jj = hoffd->j;
242: pjj = poffd->j;
243: for (i=0; i<poffd->nz; i++) {
244: jj[i] = garray[pjj[i]];
245: }
246: PetscMemcpy(hoffd->data,poffd->a,poffd->nz*sizeof(PetscScalar));
248: hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
249: HYPRE_IJMatrixAssemble(ij);
250: PetscLogEventEnd(MAT_Convert,A,0,0,0);
251: return(0);
252: }
254: /*
255: Does NOT copy the data over, instead uses DIRECTLY the pointers from the PETSc MPIAIJ format
257: This is UNFINISHED and does NOT work! The problem is that hypre puts the diagonal entry first
258: which will corrupt the PETSc data structure if we did this. Need a work around to this problem.
259: */
260: #include "_hypre_IJ_mv.h"
261: #include "HYPRE_IJ_mv.h"
265: PetscErrorCode MatHYPRE_IJMatrixLink(Mat A,HYPRE_IJMatrix *ij)
266: {
267: PetscErrorCode ierr;
268: int rstart,rend,cstart,cend;
269: PetscTruth flg;
270: hypre_ParCSRMatrix *par_matrix;
271: hypre_AuxParCSRMatrix *aux_matrix;
277: PetscTypeCompare((PetscObject)A,MATMPIAIJ,&flg);
278: if (!flg) SETERRQ(PETSC_ERR_SUP,"Can only use with PETSc MPIAIJ matrices");
279: MatPreallocated(A);
281: PetscLogEventBegin(MAT_Convert,A,0,0,0);
282: rstart = A->rmap->rstart;
283: rend = A->rmap->rend;
284: cstart = A->cmap->rstart;
285: cend = A->cmap->rend;
286: HYPRE_IJMatrixCreate(((PetscObject)A)->comm,rstart,rend-1,cstart,cend-1,ij);
287: HYPRE_IJMatrixSetObjectType(*ij,HYPRE_PARCSR);
288:
289: HYPRE_IJMatrixInitialize(*ij);
290: par_matrix = (hypre_ParCSRMatrix*)hypre_IJMatrixObject(*ij);
291: aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(*ij);
293: hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
295: /* this is the Hack part where we monkey directly with the hypre datastructures */
297: HYPRE_IJMatrixAssemble(*ij);
298: PetscLogEventEnd(MAT_Convert,A,0,0,0);
299: return(0);
300: }
302: /* -----------------------------------------------------------------------------------------------------------------*/
304: /*MC
305: MATHYPRESTRUCT - MATHYPRESTRUCT = "hyprestruct" - A matrix type to be used for parallel sparse matrices
306: based on the hypre HYPRE_StructMatrix.
309: Notes: Unlike the more general support for blocks in hypre this allows only one block per process and requires the block
310: be defined by a DA.
312: The matrix needs a DA associated with it by either a call to MatSetDA() or if the matrix is obtained from DAGetMatrix()
314: .seealso: MatCreate(), PCPFMG, MatSetDA(), DAGetMatrix()
315: M*/
317: #include petscda.h
318: #include mhyp.h
322: PetscErrorCode MatSetValuesLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
323: {
324: PetscErrorCode ierr;
325: PetscInt i,j,stencil,index[3],row,entries[7];
326: const PetscScalar *values = y;
327: Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
330: for (i=0; i<nrow; i++) {
331: for (j=0; j<ncol; j++) {
332: stencil = icol[j] - irow[i];
333: if (!stencil) {
334: entries[j] = 3;
335: } else if (stencil == -1) {
336: entries[j] = 2;
337: } else if (stencil == 1) {
338: entries[j] = 4;
339: } else if (stencil == -ex->gnx) {
340: entries[j] = 1;
341: } else if (stencil == ex->gnx) {
342: entries[j] = 5;
343: } else if (stencil == -ex->gnxgny) {
344: entries[j] = 0;
345: } else if (stencil == ex->gnxgny) {
346: entries[j] = 6;
347: } else SETERRQ3(PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
348: }
349: row = ex->gindices[irow[i]] - ex->rstart;
350: index[0] = ex->xs + (row % ex->nx);
351: index[1] = ex->ys + ((row/ex->nx) % ex->ny);
352: index[2] = ex->zs + (row/(ex->nxny));
353: if (addv == ADD_VALUES) {
354: HYPRE_StructMatrixAddToValues(ex->hmat,index,ncol,entries,(PetscScalar*)values);
355: } else {
356: HYPRE_StructMatrixSetValues(ex->hmat,index,ncol,entries,(PetscScalar*)values);
357: }
358: values += ncol;
359: }
360: return(0);
361: }
365: PetscErrorCode MatZeroRowsLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d)
366: {
367: PetscErrorCode ierr;
368: PetscInt i,index[3],row,entries[7] = {0,1,2,3,4,5,6};
369: PetscScalar values[7];
370: Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
373: PetscMemzero(values,7*sizeof(PetscScalar));
374: values[3] = d;
375: for (i=0; i<nrow; i++) {
376: row = ex->gindices[irow[i]] - ex->rstart;
377: index[0] = ex->xs + (row % ex->nx);
378: index[1] = ex->ys + ((row/ex->nx) % ex->ny);
379: index[2] = ex->zs + (row/(ex->nxny));
380: HYPRE_StructMatrixSetValues(ex->hmat,index,7,entries,values);
381: }
382: HYPRE_StructMatrixAssemble(ex->hmat);
383: return(0);
384: }
388: PetscErrorCode MatZeroEntries_HYPREStruct_3d(Mat mat)
389: {
391: PetscInt indices[7] = {0,1,2,3,4,5,6};
392: Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
395: /* hypre has no public interface to do this */
396: hypre_StructMatrixClearBoxValues(ex->hmat,&ex->hbox,7,indices,0,1);
397: HYPRE_StructMatrixAssemble(ex->hmat);
398: return(0);
399: }
403: PetscErrorCode MatSetDA_HYPREStruct(Mat mat,DA da)
404: {
405: PetscErrorCode ierr;
406: Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
407: PetscInt dim,dof,sw[3],nx,ny,nz;
408: int ilower[3],iupper[3],ssize,i;
409: DAPeriodicType p;
410: DAStencilType st;
413: ex->da = da;
414: PetscObjectReference((PetscObject)da);
416: DAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&p,&st);
417: DAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);
418: iupper[0] += ilower[0] - 1;
419: iupper[1] += ilower[1] - 1;
420: iupper[2] += ilower[2] - 1;
422: /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
423: ex->hbox.imin[0] = ilower[0];
424: ex->hbox.imin[1] = ilower[1];
425: ex->hbox.imin[2] = ilower[2];
426: ex->hbox.imax[0] = iupper[0];
427: ex->hbox.imax[1] = iupper[1];
428: ex->hbox.imax[2] = iupper[2];
430: /* create the hypre grid object and set its information */
431: if (dof > 1) SETERRQ(PETSC_ERR_SUP,"Currently only support for scalar problems");
432: if (p) SETERRQ(PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_StructGridSetPeriodic()");
433: HYPRE_StructGridCreate(ex->hcomm,dim,&ex->hgrid);
435: HYPRE_StructGridSetExtents(ex->hgrid,ilower,iupper);
436: HYPRE_StructGridAssemble(ex->hgrid);
437:
438: sw[1] = sw[0];
439: sw[2] = sw[1];
440: HYPRE_StructGridSetNumGhost(ex->hgrid,sw);
442: /* create the hypre stencil object and set its information */
443: if (sw[0] > 1) SETERRQ(PETSC_ERR_SUP,"Ask us to add support for wider stencils");
444: if (st == DA_STENCIL_BOX) SETERRQ(PETSC_ERR_SUP,"Ask us to add support for box stencils");
445: if (dim == 1) {
446: int offsets[3][1] = {{-1},{0},{1}};
447: ssize = 3;
448: HYPRE_StructStencilCreate(dim,ssize,&ex->hstencil);
449: for (i=0; i<ssize; i++) {
450: HYPRE_StructStencilSetElement(ex->hstencil,i,offsets[i]);
451: }
452: } else if (dim == 2) {
453: int offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
454: ssize = 5;
455: HYPRE_StructStencilCreate(dim,ssize,&ex->hstencil);
456: for (i=0; i<ssize; i++) {
457: HYPRE_StructStencilSetElement(ex->hstencil,i,offsets[i]);
458: }
459: } else if (dim == 3) {
460: int offsets[7][3] = {{0,0,-1},{0,-1,0},{-1,0,0},{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
461: ssize = 7;
462: HYPRE_StructStencilCreate(dim,ssize,&ex->hstencil);
463: for (i=0; i<ssize; i++) {
464: HYPRE_StructStencilSetElement(ex->hstencil,i,offsets[i]);
465: }
466: }
467:
468: /* create the HYPRE vector for rhs and solution */
469: HYPRE_StructVectorCreate(ex->hcomm,ex->hgrid,&ex->hb);
470: HYPRE_StructVectorCreate(ex->hcomm,ex->hgrid,&ex->hx);
471: HYPRE_StructVectorInitialize(ex->hb);
472: HYPRE_StructVectorInitialize(ex->hx);
473: HYPRE_StructVectorAssemble(ex->hb);
474: HYPRE_StructVectorAssemble(ex->hx);
476: /* create the hypre matrix object and set its information */
477: HYPRE_StructMatrixCreate(ex->hcomm,ex->hgrid,ex->hstencil,&ex->hmat);
478: HYPRE_StructGridDestroy(ex->hgrid);
479: HYPRE_StructStencilDestroy(ex->hstencil);CHKERRQ(ierr)
480: if (ex->needsinitialization) {
481: HYPRE_StructMatrixInitialize(ex->hmat);
482: ex->needsinitialization = PETSC_FALSE;
483: }
485: /* set the global and local sizes of the matrix */
486: DAGetCorners(da,0,0,0,&nx,&ny,&nz);
487: MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);
488: PetscLayoutSetBlockSize(mat->rmap,1);
489: PetscLayoutSetBlockSize(mat->cmap,1);
490: PetscLayoutSetUp(mat->rmap);
491: PetscLayoutSetUp(mat->cmap);
493: if (dim == 3) {
494: mat->ops->setvalueslocal = MatSetValuesLocal_HYPREStruct_3d;
495: mat->ops->zerorowslocal = MatZeroRowsLocal_HYPREStruct_3d;
496: mat->ops->zeroentries = MatZeroEntries_HYPREStruct_3d;
497: MatZeroEntries_HYPREStruct_3d(mat);
498: } else SETERRQ(PETSC_ERR_SUP,"Only support for 3d DA currently");
500: /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
501: MatGetOwnershipRange(mat,&ex->rstart,PETSC_NULL);
502: DAGetGlobalIndices(ex->da,PETSC_NULL,&ex->gindices);
503: DAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,0);
504: ex->gnxgny *= ex->gnx;
505: DAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,0);
506: ex->nxny = ex->nx*ex->ny;
507: return(0);
508: }
512: PetscErrorCode MatMult_HYPREStruct(Mat A,Vec x,Vec y)
513: {
514: PetscErrorCode ierr;
515: PetscScalar *xx,*yy;
516: int ilower[3],iupper[3];
517: Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(A->data);
520: DAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);
521: iupper[0] += ilower[0] - 1;
522: iupper[1] += ilower[1] - 1;
523: iupper[2] += ilower[2] - 1;
525: /* copy x values over to hypre */
526: HYPRE_StructVectorSetConstantValues(mx->hb,0.0);
527: VecGetArray(x,&xx);
528: HYPRE_StructVectorSetBoxValues(mx->hb,ilower,iupper,xx);
529: VecRestoreArray(x,&xx);
530: HYPRE_StructVectorAssemble(mx->hb);
532: HYPRE_StructMatrixMatvec(1.0,mx->hmat,mx->hb,0.0,mx->hx);
534: /* copy solution values back to PETSc */
535: VecGetArray(y,&yy);
536: HYPRE_StructVectorGetBoxValues(mx->hx,ilower,iupper,yy);
537: VecRestoreArray(y,&yy);
538: return(0);
539: }
543: PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat,MatAssemblyType mode)
544: {
545: Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
546: PetscErrorCode ierr;
549: HYPRE_StructMatrixAssemble(ex->hmat);
550: /* HYPRE_StructMatrixPrint("dummy",ex->hmat,0); */
551: return(0);
552: }
556: PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat)
557: {
559: /* before the DA is set to the matrix the zero doesn't need to do anything */
560: return(0);
561: }
566: PetscErrorCode MatDestroy_HYPREStruct(Mat mat)
567: {
568: Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
569: PetscErrorCode ierr;
572: HYPRE_StructMatrixDestroy(ex->hmat);
573: HYPRE_StructVectorDestroy(ex->hx);
574: HYPRE_StructVectorDestroy(ex->hb);
575: return(0);
576: }
582: PetscErrorCode MatCreate_HYPREStruct(Mat B)
583: {
584: Mat_HYPREStruct *ex;
585: PetscErrorCode ierr;
588: PetscNewLog(B,Mat_HYPREStruct,&ex);
589: B->data = (void*)ex;
590: B->rmap->bs = 1;
591: B->assembled = PETSC_FALSE;
592: B->mapping = 0;
594: B->insertmode = NOT_SET_VALUES;
596: B->ops->assemblyend = MatAssemblyEnd_HYPREStruct;
597: B->ops->mult = MatMult_HYPREStruct;
598: B->ops->zeroentries = MatZeroEntries_HYPREStruct;
599: B->ops->destroy = MatDestroy_HYPREStruct;
601: ex->needsinitialization = PETSC_TRUE;
603: MPI_Comm_dup(((PetscObject)B)->comm,&(ex->hcomm));
604: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSetDA_C","MatSetDA_HYPREStruct",MatSetDA_HYPREStruct);
605: PetscObjectChangeTypeName((PetscObject)B,MATHYPRESTRUCT);
606: return(0);
607: }
611: /*MC
612: MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices
613: based on the hypre HYPRE_SStructMatrix.
614:
615:
616: Notes: Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured
617: grid objects, we will restrict the semi-struct objects to consist of only structured-grid components.
619: Unlike the more general support for parts and blocks in hypre this allows only one part, and one block per process and requires the block
620: be defined by a DA.
621:
622: The matrix needs a DA associated with it by either a call to MatSetDA() or if the matrix is obtained from DAGetMatrix()
623:
624: M*/
628: PetscErrorCode MatSetValuesLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
629: {
630: PetscErrorCode ierr;
631: PetscInt i,j,stencil,index[3];
632: const PetscScalar *values = y;
633: Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
635: int part= 0; /* Petsc sstruct interface only allows 1 part */
636: int ordering;
637: int grid_rank, to_grid_rank;
638: int var_type, to_var_type;
639: int to_var_entry = 0;
641: int nvars= ex->nvars;
642: PetscInt row,*entries;
645: PetscMalloc(7*nvars*sizeof(PetscInt),&entries);
647: ordering= ex-> dofs_order; /* ordering= 0 nodal ordering
648: 1 variable ordering */
649: /* stencil entries are orderer by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ... */
651: if (!ordering) /* nodal ordering */
652: {
653: for (i=0; i<nrow; i++) {
654: grid_rank= irow[i]/nvars;
655: var_type = (irow[i] % nvars);
657: for (j=0; j<ncol; j++) {
658: to_grid_rank= icol[j]/nvars;
659: to_var_type = (icol[j] % nvars);
661: to_var_entry= to_var_entry*7;
662: entries[j]= to_var_entry;
664: stencil = to_grid_rank-grid_rank;
665: if (!stencil) {
666: entries[j] += 3;
667: } else if (stencil == -1) {
668: entries[j] += 2;
669: } else if (stencil == 1) {
670: entries[j] += 4;
671: } else if (stencil == -ex->gnx) {
672: entries[j] += 1;
673: } else if (stencil == ex->gnx) {
674: entries[j] += 5;
675: } else if (stencil == -ex->gnxgny) {
676: entries[j] += 0;
677: } else if (stencil == ex->gnxgny) {
678: entries[j] += 6;
679: } else SETERRQ3(PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
680: }
682: row = ex->gindices[grid_rank] - ex->rstart;
683: index[0] = ex->xs + (row % ex->nx);
684: index[1] = ex->ys + ((row/ex->nx) % ex->ny);
685: index[2] = ex->zs + (row/(ex->nxny));
687: if (addv == ADD_VALUES) {
688: HYPRE_SStructMatrixAddToValues(ex->ss_mat,part,index,var_type,ncol,entries,(PetscScalar*)values);
689: } else {
690: HYPRE_SStructMatrixSetValues(ex->ss_mat,part,index,var_type,ncol,entries,(PetscScalar*)values);
691: }
692: values += ncol;
693: }
694: }
696: else
697: {
698: for (i=0; i<nrow; i++) {
699: var_type = irow[i]/(ex->gnxgnygnz);
700: grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
702: for (j=0; j<ncol; j++) {
703: to_var_type = icol[j]/(ex->gnxgnygnz);
704: to_grid_rank= icol[j] - to_var_type*(ex->gnxgnygnz);
706: to_var_entry= to_var_entry*7;
707: entries[j]= to_var_entry;
709: stencil = to_grid_rank-grid_rank;
710: if (!stencil) {
711: entries[j] += 3;
712: } else if (stencil == -1) {
713: entries[j] += 2;
714: } else if (stencil == 1) {
715: entries[j] += 4;
716: } else if (stencil == -ex->gnx) {
717: entries[j] += 1;
718: } else if (stencil == ex->gnx) {
719: entries[j] += 5;
720: } else if (stencil == -ex->gnxgny) {
721: entries[j] += 0;
722: } else if (stencil == ex->gnxgny) {
723: entries[j] += 6;
724: } else SETERRQ3(PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
725: }
727: row = ex->gindices[grid_rank] - ex->rstart;
728: index[0] = ex->xs + (row % ex->nx);
729: index[1] = ex->ys + ((row/ex->nx) % ex->ny);
730: index[2] = ex->zs + (row/(ex->nxny));
732: if (addv == ADD_VALUES) {
733: HYPRE_SStructMatrixAddToValues(ex->ss_mat,part,index,var_type,ncol,entries,(PetscScalar*)values);
734: } else {
735: HYPRE_SStructMatrixSetValues(ex->ss_mat,part,index,var_type,ncol,entries,(PetscScalar*)values);
736: }
737: values += ncol;
738: }
740: }
741: PetscFree(entries);
742: return(0);
743: }
747: PetscErrorCode MatZeroRowsLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d)
748: {
749: PetscErrorCode ierr;
750: PetscInt i,index[3];
751: PetscScalar **values;
752: Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
754: int part= 0; /* Petsc sstruct interface only allows 1 part */
755: int ordering= ex->dofs_order;
756: int grid_rank;
757: int var_type;
758: int nvars= ex->nvars;
759: PetscInt row,*entries;
762: PetscMalloc(7*nvars*sizeof(PetscInt),&entries);
764: PetscMalloc(nvars*sizeof(PetscScalar *),&values);
765: PetscMalloc(7*nvars*nvars*sizeof(PetscScalar),&values[0]);
766: for (i=1; i<nvars; i++) {
767: values[i] = values[i-1] + nvars*7;
768: }
770: for (i=0; i< nvars; i++) {
771: PetscMemzero(values[i],nvars*7*sizeof(PetscScalar));
772: *(values[i]+3)= d;
773: }
775: for (i= 0; i< nvars*7; i++) {
776: entries[i]= i;
777: }
779: if (!ordering) {
780: for (i=0; i<nrow; i++) {
781: grid_rank= irow[i]/nvars;
782: var_type = (irow[i] % nvars);
784: row = ex->gindices[grid_rank] - ex->rstart;
785: index[0] = ex->xs + (row % ex->nx);
786: index[1] = ex->ys + ((row/ex->nx) % ex->ny);
787: index[2] = ex->zs + (row/(ex->nxny));
788: HYPRE_SStructMatrixSetValues(ex->ss_mat,part,index,var_type,7*nvars,entries,values[var_type]);
789: }
790: }
791:
792: else {
793: for (i=0; i<nrow; i++) {
794: var_type = irow[i]/(ex->gnxgnygnz);
795: grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
797: row = ex->gindices[grid_rank] - ex->rstart;
798: index[0] = ex->xs + (row % ex->nx);
799: index[1] = ex->ys + ((row/ex->nx) % ex->ny);
800: index[2] = ex->zs + (row/(ex->nxny));
801: HYPRE_SStructMatrixSetValues(ex->ss_mat,part,index,var_type,7*nvars,entries,values[var_type]);
802: }
803: }
805: HYPRE_SStructMatrixAssemble(ex->ss_mat);
807: PetscFree(values[0]);
808: PetscFree(values);
810: PetscFree(entries);
811: return(0);
812: }
816: PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat)
817: {
818: PetscErrorCode ierr;
819: Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
820: int nvars= ex->nvars;
821: int size;
822: int part= 0; /* only one part */
826: size= ((ex->hbox.imax[0])-(ex->hbox.imin[0])+1)*((ex->hbox.imax[1])-(ex->hbox.imin[1])+1)*((ex->hbox.imax[2])-(ex->hbox.imin[2])+1);
827: {
828: PetscInt i,*entries;
829: PetscScalar *values;
830: int iupper[3], ilower[3];
831:
832: for (i= 0; i< 3; i++) {
833: ilower[i]= ex->hbox.imin[i];
834: iupper[i]= ex->hbox.imax[i];
835: }
837: PetscMalloc2(nvars*7,PetscInt,&entries,nvars*7*size,PetscScalar,&values);
838: for (i= 0; i< nvars*7; i++) {
839: entries[i]= i;
840: }
842: PetscMemzero(values,nvars*7*size*sizeof(PetscScalar));
844: for (i= 0; i< nvars; i++) {
845: HYPRE_SStructMatrixSetBoxValues(ex->ss_mat,part,ilower,iupper,i,nvars*7,entries,values);
846: }
848: PetscFree2(entries,values);
849: }
851: HYPRE_SStructMatrixAssemble(ex->ss_mat);
853: return(0);
854: }
859: PetscErrorCode MatSetDA_HYPRESStruct(Mat mat,DA da)
860: {
861: PetscErrorCode ierr;
862: Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
863: PetscInt dim,dof,sw[3],nx,ny,nz;
864: int ilower[3],iupper[3],ssize,i;
865: DAPeriodicType p;
866: DAStencilType st;
867: int nparts= 1; /* assuming only one part */
868: int part = 0;
871: ex->da = da;
872: PetscObjectReference((PetscObject)da);
874: DAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&p,&st);
875: DAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);
876: iupper[0] += ilower[0] - 1;
877: iupper[1] += ilower[1] - 1;
878: iupper[2] += ilower[2] - 1;
879: /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
880: ex->hbox.imin[0] = ilower[0];
881: ex->hbox.imin[1] = ilower[1];
882: ex->hbox.imin[2] = ilower[2];
883: ex->hbox.imax[0] = iupper[0];
884: ex->hbox.imax[1] = iupper[1];
885: ex->hbox.imax[2] = iupper[2];
887: ex->dofs_order = 0;
889: /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */
890: ex->nvars= dof;
892: /* create the hypre grid object and set its information */
893: if (p) SETERRQ(PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()");
894: HYPRE_SStructGridCreate(ex->hcomm,dim,nparts,&ex->ss_grid);
896: HYPRE_SStructGridSetExtents(ex->ss_grid,part,ex->hbox.imin,ex->hbox.imax);
898: {
899: HYPRE_SStructVariable *vartypes;
900: PetscMalloc(ex->nvars*sizeof(HYPRE_SStructVariable),&vartypes);
901: for (i= 0; i< ex->nvars; i++) {
902: vartypes[i]= HYPRE_SSTRUCT_VARIABLE_CELL;
903: }
904: HYPRE_SStructGridSetVariables(ex->ss_grid, part, ex->nvars,vartypes);
905: PetscFree(vartypes);
906: }
908: HYPRE_SStructGridAssemble(ex->ss_grid);
910: sw[1] = sw[0];
911: sw[2] = sw[1];
912: // HYPRE_SStructGridSetNumGhost(ex->ss_grid,sw);
914: /* create the hypre stencil object and set its information */
915: if (sw[0] > 1) SETERRQ(PETSC_ERR_SUP,"Ask us to add support for wider stencils");
916: if (st == DA_STENCIL_BOX) SETERRQ(PETSC_ERR_SUP,"Ask us to add support for box stencils");
918: if (dim == 1) {
919: int offsets[3][1] = {{-1},{0},{1}};
920: int j, cnt;
922: ssize = 3*(ex->nvars);
923: HYPRE_SStructStencilCreate(dim,ssize,&ex->ss_stencil);
924: cnt= 0;
925: for (i= 0; i< (ex->nvars); i++) {
926: for (j= 0; j< 3; j++) {
927: HYPRE_SStructStencilSetEntry(ex->ss_stencil, cnt, offsets[j], i);
928: cnt++;
929: }
930: }
932: } else if (dim == 2) {
933: int offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
934: int j, cnt;
936: ssize = 5*(ex->nvars);
937: HYPRE_SStructStencilCreate(dim,ssize,&ex->ss_stencil);
938: cnt= 0;
939: for (i= 0; i< (ex->nvars); i++) {
940: for (j= 0; j< 5; j++) {
941: HYPRE_SStructStencilSetEntry(ex->ss_stencil, cnt, offsets[j], i);
942: cnt++;
943: }
944: }
945: } else if (dim == 3) {
946: int offsets[7][3] = {{0,0,-1},{0,-1,0},{-1,0,0},{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
947: int j, cnt;
949: ssize = 7*(ex->nvars);
950: HYPRE_SStructStencilCreate(dim,ssize,&ex->ss_stencil);
951: cnt= 0;
952: for (i= 0; i< (ex->nvars); i++) {
953: for (j= 0; j< 7; j++) {
954: HYPRE_SStructStencilSetEntry(ex->ss_stencil, cnt, offsets[j], i);
955: cnt++;
956: }
957: }
958: }
960: /* create the HYPRE graph */
961: HYPRE_SStructGraphCreate(ex->hcomm, ex->ss_grid, &(ex->ss_graph));
963: /* set the stencil graph. Note that each variable has the same graph. This means that each
964: variable couples to all the other variable and with the same stencil pattern. */
965: for (i= 0; i< (ex->nvars); i++) {
966: HYPRE_SStructGraphSetStencil(ex->ss_graph,part,i,ex->ss_stencil);
967: }
968: ierr= HYPRE_SStructGraphAssemble(ex->ss_graph);
970: /* create the HYPRE sstruct vectors for rhs and solution */
971: HYPRE_SStructVectorCreate(ex->hcomm,ex->ss_grid,&ex->ss_b);
972: HYPRE_SStructVectorCreate(ex->hcomm,ex->ss_grid,&ex->ss_x);
973: HYPRE_SStructVectorInitialize(ex->ss_b);
974: HYPRE_SStructVectorInitialize(ex->ss_x);
975: HYPRE_SStructVectorAssemble(ex->ss_b);
976: HYPRE_SStructVectorAssemble(ex->ss_x);
978: /* create the hypre matrix object and set its information */
979: HYPRE_SStructMatrixCreate(ex->hcomm,ex->ss_graph,&ex->ss_mat);
980: HYPRE_SStructGridDestroy(ex->ss_grid);
981: HYPRE_SStructStencilDestroy(ex->ss_stencil);CHKERRQ(ierr)
982: if (ex->needsinitialization) {
983: HYPRE_SStructMatrixInitialize(ex->ss_mat);
984: ex->needsinitialization = PETSC_FALSE;
985: }
986:
988: /* set the global and local sizes of the matrix */
989: DAGetCorners(da,0,0,0,&nx,&ny,&nz);
990: MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);
991: PetscLayoutSetBlockSize(mat->rmap,1);
992: PetscLayoutSetBlockSize(mat->cmap,1);
993: PetscLayoutSetUp(mat->rmap);
994: PetscLayoutSetUp(mat->cmap);
995:
996: if (dim == 3) {
997: mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d;
998: mat->ops->zerorowslocal = MatZeroRowsLocal_HYPRESStruct_3d;
999: mat->ops->zeroentries = MatZeroEntries_HYPRESStruct_3d;
1000: MatZeroEntries_HYPRESStruct_3d(mat);
1001: } else SETERRQ(PETSC_ERR_SUP,"Only support for 3d DA currently");
1002:
1003: /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
1004: MatGetOwnershipRange(mat,&ex->rstart,PETSC_NULL);
1005: DAGetGlobalIndices(ex->da,PETSC_NULL,&ex->gindices);
1006: DAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,&ex->gnxgnygnz);
1007: ex->gnxgny *= ex->gnx;
1008: ex->gnxgnygnz *= ex->gnxgny;
1009: DAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,&ex->nz);
1010: ex->nxny = ex->nx*ex->ny;
1011: ex->nxnynz = ex->nz*ex->nxny;
1012: return(0);
1013: }
1014:
1017: PetscErrorCode MatMult_HYPRESStruct(Mat A,Vec x,Vec y)
1018: {
1019: PetscErrorCode ierr;
1020: PetscScalar *xx,*yy;
1021: int ilower[3],iupper[3];
1022: Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(A->data);
1023: int ordering= mx->dofs_order;
1024: int nvars= mx->nvars;
1025: int part= 0;
1026: int size;
1027: int i;
1028:
1030: DAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);
1031: iupper[0] += ilower[0] - 1;
1032: iupper[1] += ilower[1] - 1;
1033: iupper[2] += ilower[2] - 1;
1035: size= 1;
1036: for (i= 0; i< 3; i++) {
1037: size*= (iupper[i]-ilower[i]+1);
1038: }
1040: /* copy x values over to hypre for variable ordering */
1041: if (ordering) {
1042: HYPRE_SStructVectorSetConstantValues(mx->ss_b,0.0);
1043: VecGetArray(x,&xx);
1044: for (i= 0; i< nvars; i++) {
1045: HYPRE_SStructVectorSetBoxValues(mx->ss_b,part,ilower,iupper,i,xx+(size*i));
1046: }
1047: VecRestoreArray(x,&xx);
1048: HYPRE_SStructVectorAssemble(mx->ss_b);
1049:
1050: HYPRE_SStructMatrixMatvec(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x);
1052: /* copy solution values back to PETSc */
1053: VecGetArray(y,&yy);
1054: for (i= 0; i< nvars; i++) {
1055: HYPRE_SStructVectorGetBoxValues(mx->ss_x,part,ilower,iupper,i,yy+(size*i));
1056: }
1057: VecRestoreArray(y,&yy);
1058: }
1060: else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
1061: PetscScalar *z;
1062: int j, k;
1064: PetscMalloc(nvars*size*sizeof(PetscScalar),&z);
1065: HYPRE_SStructVectorSetConstantValues(mx->ss_b,0.0);
1066: VecGetArray(x,&xx);
1068: /* transform nodal to hypre's variable ordering for sys_pfmg */
1069: for (i= 0; i< size; i++) {
1070: k= i*nvars;
1071: for (j= 0; j< nvars; j++) {
1072: z[j*size+i]= xx[k+j];
1073: }
1074: }
1075: for (i= 0; i< nvars; i++) {
1076: HYPRE_SStructVectorSetBoxValues(mx->ss_b,part,ilower,iupper,i,z+(size*i));
1077: }
1078: VecRestoreArray(x,&xx);
1080: HYPRE_SStructVectorAssemble(mx->ss_b);
1081:
1082: HYPRE_SStructMatrixMatvec(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x);
1083:
1084: /* copy solution values back to PETSc */
1085: VecGetArray(y,&yy);
1086: for (i= 0; i< nvars; i++) {
1087: HYPRE_SStructVectorGetBoxValues(mx->ss_x,part,ilower,iupper,i,z+(size*i));
1088: }
1089: /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
1090: for (i= 0; i< size; i++) {
1091: k= i*nvars;
1092: for (j= 0; j< nvars; j++) {
1093: yy[k+j]= z[j*size+i];
1094: }
1095: }
1096: VecRestoreArray(y,&yy);
1098: PetscFree(z);
1099: }
1101: return(0);
1102: }
1106: PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat,MatAssemblyType mode)
1107: {
1108: Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
1109: PetscErrorCode ierr;
1112: printf("look 1\n");
1113: HYPRE_SStructMatrixAssemble(ex->ss_mat);
1114: printf("look 2\n");
1115: return(0);
1116: }
1120: PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat)
1121: {
1123: /* before the DA is set to the matrix the zero doesn't need to do anything */
1124: return(0);
1125: }
1130: PetscErrorCode MatDestroy_HYPRESStruct(Mat mat)
1131: {
1132: Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
1133: PetscErrorCode ierr;
1136: HYPRE_SStructGraphDestroy(ex->ss_graph);
1137: HYPRE_SStructMatrixDestroy(ex->ss_mat);
1138: HYPRE_SStructVectorDestroy(ex->ss_x);
1139: HYPRE_SStructVectorDestroy(ex->ss_b);
1140: return(0);
1141: }
1146: PetscErrorCode MatCreate_HYPRESStruct(Mat B)
1147: {
1148: Mat_HYPRESStruct *ex;
1149: PetscErrorCode ierr;
1152: PetscNewLog(B,Mat_HYPRESStruct,&ex);
1153: B->data = (void*)ex;
1154: B->rmap->bs = 1;
1155: B->assembled = PETSC_FALSE;
1156: B->mapping = 0;
1158: B->insertmode = NOT_SET_VALUES;
1160: B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct;
1161: B->ops->mult = MatMult_HYPRESStruct;
1162: B->ops->zeroentries = MatZeroEntries_HYPRESStruct;
1163: B->ops->destroy = MatDestroy_HYPRESStruct;
1165: ex->needsinitialization = PETSC_TRUE;
1166:
1167: MPI_Comm_dup(((PetscObject)B)->comm,&(ex->hcomm));
1168: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSetDA_C","MatSetDA_HYPRESStruct",MatSetDA_HYPRESStruct);
1169: PetscObjectChangeTypeName((PetscObject)B,MATHYPRESSTRUCT);
1170: return(0);
1171: }
1174: #endif