xref: /petsc/src/dm/impls/da/hypre/mhyp.c (revision fd3f9acd5cadffcc22fcaa614b6eee3ffc5ae216)
1f4bdf6c4SBarry Smith 
2f4bdf6c4SBarry Smith /*
3f4bdf6c4SBarry Smith     Creates hypre ijmatrix from PETSc matrix
4f4bdf6c4SBarry Smith */
5c6db04a5SJed Brown #include <petscsys.h>
6b45d2f2cSJed Brown #include <petsc-private/matimpl.h>          /*I "petscmat.h" I*/
7c6db04a5SJed Brown #include <petscdmda.h>                /*I "petscdmda.h" I*/
8c6db04a5SJed Brown #include <../src/dm/impls/da/hypre/mhyp.h>
9f4bdf6c4SBarry Smith 
10f4bdf6c4SBarry Smith #undef __FUNCT__
11f4bdf6c4SBarry Smith #define __FUNCT__ "MatHYPRE_IJMatrixPreallocate"
12f4bdf6c4SBarry Smith PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o,HYPRE_IJMatrix ij)
13f4bdf6c4SBarry Smith {
14f4bdf6c4SBarry Smith   PetscErrorCode ierr;
151a83f524SJed Brown   PetscInt       i,n_d,n_o;
161a83f524SJed Brown   const PetscInt *ia_d,*ia_o;
17f4bdf6c4SBarry Smith   PetscBool      done_d=PETSC_FALSE,done_o=PETSC_FALSE;
18f4bdf6c4SBarry Smith   PetscInt       *nnz_d=PETSC_NULL,*nnz_o=PETSC_NULL;
19f4bdf6c4SBarry Smith 
20f4bdf6c4SBarry Smith   PetscFunctionBegin;
21f4bdf6c4SBarry Smith   if (A_d) { /* determine number of nonzero entries in local diagonal part */
22f4bdf6c4SBarry Smith     ierr = MatGetRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,&n_d,&ia_d,PETSC_NULL,&done_d);CHKERRQ(ierr);
23f4bdf6c4SBarry Smith     if (done_d) {
24f4bdf6c4SBarry Smith       ierr = PetscMalloc(n_d*sizeof(PetscInt),&nnz_d);CHKERRQ(ierr);
25f4bdf6c4SBarry Smith       for (i=0; i<n_d; i++) {
26f4bdf6c4SBarry Smith         nnz_d[i] = ia_d[i+1] - ia_d[i];
27f4bdf6c4SBarry Smith       }
28f4bdf6c4SBarry Smith     }
29f4bdf6c4SBarry Smith     ierr = MatRestoreRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,&n_d,&ia_d,PETSC_NULL,&done_d);CHKERRQ(ierr);
30f4bdf6c4SBarry Smith   }
31f4bdf6c4SBarry Smith   if (A_o) { /* determine number of nonzero entries in local off-diagonal part */
32f4bdf6c4SBarry Smith     ierr = MatGetRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,PETSC_NULL,&done_o);CHKERRQ(ierr);
33f4bdf6c4SBarry Smith     if (done_o) {
34f4bdf6c4SBarry Smith       ierr = PetscMalloc(n_o*sizeof(PetscInt),&nnz_o);CHKERRQ(ierr);
35f4bdf6c4SBarry Smith       for (i=0; i<n_o; i++) {
36f4bdf6c4SBarry Smith         nnz_o[i] = ia_o[i+1] - ia_o[i];
37f4bdf6c4SBarry Smith       }
38f4bdf6c4SBarry Smith     }
39f4bdf6c4SBarry Smith     ierr = MatRestoreRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,PETSC_NULL,&done_o);CHKERRQ(ierr);
40f4bdf6c4SBarry Smith   }
41f4bdf6c4SBarry Smith   if (done_d) {    /* set number of nonzeros in HYPRE IJ matrix */
42f4bdf6c4SBarry Smith     if (!done_o) { /* only diagonal part */
43f4bdf6c4SBarry Smith       ierr = PetscMalloc(n_d*sizeof(PetscInt),&nnz_o);CHKERRQ(ierr);
44f4bdf6c4SBarry Smith       for (i=0; i<n_d; i++) {
45f4bdf6c4SBarry Smith         nnz_o[i] = 0;
46f4bdf6c4SBarry Smith       }
47f4bdf6c4SBarry Smith     }
48*fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(ij,nnz_d,nnz_o));
49f4bdf6c4SBarry Smith     ierr = PetscFree(nnz_d);CHKERRQ(ierr);
50f4bdf6c4SBarry Smith     ierr = PetscFree(nnz_o);CHKERRQ(ierr);
51f4bdf6c4SBarry Smith   }
52f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
53f4bdf6c4SBarry Smith }
54f4bdf6c4SBarry Smith 
55f4bdf6c4SBarry Smith #undef __FUNCT__
56f4bdf6c4SBarry Smith #define __FUNCT__ "MatHYPRE_IJMatrixCreate"
57f4bdf6c4SBarry Smith PetscErrorCode MatHYPRE_IJMatrixCreate(Mat A,HYPRE_IJMatrix *ij)
58f4bdf6c4SBarry Smith {
59f4bdf6c4SBarry Smith   PetscErrorCode ierr;
604ddd07fcSJed Brown   PetscInt       rstart,rend,cstart,cend;
61f4bdf6c4SBarry Smith 
62f4bdf6c4SBarry Smith   PetscFunctionBegin;
63f4bdf6c4SBarry Smith   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
64f4bdf6c4SBarry Smith   PetscValidType(A,1);
65f4bdf6c4SBarry Smith   PetscValidPointer(ij,2);
664994cf47SJed Brown   ierr = MatSetUp(A);CHKERRQ(ierr);
67f4bdf6c4SBarry Smith   rstart = A->rmap->rstart;
68f4bdf6c4SBarry Smith   rend   = A->rmap->rend;
69f4bdf6c4SBarry Smith   cstart = A->cmap->rstart;
70f4bdf6c4SBarry Smith   cend   = A->cmap->rend;
71*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_IJMatrixCreate,(((PetscObject)A)->comm,rstart,rend-1,cstart,cend-1,ij));
72*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(*ij,HYPRE_PARCSR));
73f4bdf6c4SBarry Smith   {
74f4bdf6c4SBarry Smith     PetscBool   same;
75f4bdf6c4SBarry Smith     Mat         A_d,A_o;
761a83f524SJed Brown     const PetscInt *colmap;
77251f4c67SDmitry Karpeev     ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&same);CHKERRQ(ierr);
78f4bdf6c4SBarry Smith     if (same) {
79f4bdf6c4SBarry Smith       ierr = MatMPIAIJGetSeqAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr);
80f4bdf6c4SBarry Smith       ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,*ij);CHKERRQ(ierr);
81f4bdf6c4SBarry Smith       PetscFunctionReturn(0);
82f4bdf6c4SBarry Smith     }
83251f4c67SDmitry Karpeev     ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&same);CHKERRQ(ierr);
84f4bdf6c4SBarry Smith     if (same) {
85f4bdf6c4SBarry Smith       ierr = MatMPIBAIJGetSeqBAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr);
86f4bdf6c4SBarry Smith       ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,*ij);CHKERRQ(ierr);
87f4bdf6c4SBarry Smith       PetscFunctionReturn(0);
88f4bdf6c4SBarry Smith     }
89251f4c67SDmitry Karpeev     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&same);CHKERRQ(ierr);
90f4bdf6c4SBarry Smith     if (same) {
91f4bdf6c4SBarry Smith       ierr = MatHYPRE_IJMatrixPreallocate(A,PETSC_NULL,*ij);CHKERRQ(ierr);
92f4bdf6c4SBarry Smith       PetscFunctionReturn(0);
93f4bdf6c4SBarry Smith     }
94251f4c67SDmitry Karpeev     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQBAIJ,&same);CHKERRQ(ierr);
95f4bdf6c4SBarry Smith     if (same) {
96f4bdf6c4SBarry Smith       ierr = MatHYPRE_IJMatrixPreallocate(A,PETSC_NULL,*ij);CHKERRQ(ierr);
97f4bdf6c4SBarry Smith       PetscFunctionReturn(0);
98f4bdf6c4SBarry Smith     }
99f4bdf6c4SBarry Smith   }
100f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
101f4bdf6c4SBarry Smith }
102f4bdf6c4SBarry Smith 
103f4bdf6c4SBarry Smith extern PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat,HYPRE_IJMatrix);
104f4bdf6c4SBarry Smith extern PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat,HYPRE_IJMatrix);
105f4bdf6c4SBarry Smith /*
106f4bdf6c4SBarry Smith     Copies the data over (column indices, numerical values) to hypre matrix
107f4bdf6c4SBarry Smith */
108f4bdf6c4SBarry Smith 
109f4bdf6c4SBarry Smith #undef __FUNCT__
110f4bdf6c4SBarry Smith #define __FUNCT__ "MatHYPRE_IJMatrixCopy"
111f4bdf6c4SBarry Smith PetscErrorCode MatHYPRE_IJMatrixCopy(Mat A,HYPRE_IJMatrix ij)
112f4bdf6c4SBarry Smith {
113f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
114f4bdf6c4SBarry Smith   PetscInt          i,rstart,rend,ncols;
115f4bdf6c4SBarry Smith   const PetscScalar *values;
116f4bdf6c4SBarry Smith   const PetscInt    *cols;
117f4bdf6c4SBarry Smith   PetscBool         flg;
118f4bdf6c4SBarry Smith 
119f4bdf6c4SBarry Smith   PetscFunctionBegin;
120251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&flg);CHKERRQ(ierr);
121f4bdf6c4SBarry Smith   if (flg) {
122f4bdf6c4SBarry Smith     ierr = MatHYPRE_IJMatrixFastCopy_MPIAIJ(A,ij);CHKERRQ(ierr);
123f4bdf6c4SBarry Smith     PetscFunctionReturn(0);
124f4bdf6c4SBarry Smith   }
125251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&flg);CHKERRQ(ierr);
126f4bdf6c4SBarry Smith   if (flg) {
127f4bdf6c4SBarry Smith     ierr = MatHYPRE_IJMatrixFastCopy_SeqAIJ(A,ij);CHKERRQ(ierr);
128f4bdf6c4SBarry Smith     PetscFunctionReturn(0);
129f4bdf6c4SBarry Smith   }
130f4bdf6c4SBarry Smith 
131f4bdf6c4SBarry Smith   ierr = PetscLogEventBegin(MAT_Convert,A,0,0,0);CHKERRQ(ierr);
132*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij));
133f4bdf6c4SBarry Smith   ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr);
134f4bdf6c4SBarry Smith   for (i=rstart; i<rend; i++) {
135f4bdf6c4SBarry Smith     ierr = MatGetRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr);
136*fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_IJMatrixSetValues,(ij,1,&ncols,&i,cols,values));
137f4bdf6c4SBarry Smith     ierr = MatRestoreRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr);
138f4bdf6c4SBarry Smith   }
139*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_IJMatrixAssemble,(ij));
140f4bdf6c4SBarry Smith   ierr = PetscLogEventEnd(MAT_Convert,A,0,0,0);CHKERRQ(ierr);
141f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
142f4bdf6c4SBarry Smith }
143f4bdf6c4SBarry Smith 
144f4bdf6c4SBarry Smith /*
145f4bdf6c4SBarry Smith     This copies the CSR format directly from the PETSc data structure to the hypre
146f4bdf6c4SBarry Smith     data structure without calls to MatGetRow() or hypre's set values.
147f4bdf6c4SBarry Smith 
148f4bdf6c4SBarry Smith */
149c6db04a5SJed Brown #include <_hypre_IJ_mv.h>
150c6db04a5SJed Brown #include <HYPRE_IJ_mv.h>
151c6db04a5SJed Brown #include <../src/mat/impls/aij/mpi/mpiaij.h>
152f4bdf6c4SBarry Smith 
153f4bdf6c4SBarry Smith #undef __FUNCT__
154f4bdf6c4SBarry Smith #define __FUNCT__ "MatHYPRE_IJMatrixFastCopy_SeqAIJ"
155f4bdf6c4SBarry Smith PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat A,HYPRE_IJMatrix ij)
156f4bdf6c4SBarry Smith {
157f4bdf6c4SBarry Smith   PetscErrorCode        ierr;
158e497e08cSBarry Smith   Mat_SeqAIJ            *pdiag = (Mat_SeqAIJ*)A->data;
159f4bdf6c4SBarry Smith 
160f4bdf6c4SBarry Smith   hypre_ParCSRMatrix    *par_matrix;
161f4bdf6c4SBarry Smith   hypre_AuxParCSRMatrix *aux_matrix;
16225578ef6SJed Brown   hypre_CSRMatrix       *hdiag;
163f4bdf6c4SBarry Smith 
164f4bdf6c4SBarry Smith   PetscFunctionBegin;
165f4bdf6c4SBarry Smith   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
166f4bdf6c4SBarry Smith   PetscValidType(A,1);
167f4bdf6c4SBarry Smith   PetscValidPointer(ij,2);
168f4bdf6c4SBarry Smith 
169f4bdf6c4SBarry Smith   ierr = PetscLogEventBegin(MAT_Convert,A,0,0,0);CHKERRQ(ierr);
170*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij));
171f4bdf6c4SBarry Smith   par_matrix = (hypre_ParCSRMatrix*)hypre_IJMatrixObject(ij);
172f4bdf6c4SBarry Smith   aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
173f4bdf6c4SBarry Smith   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
174f4bdf6c4SBarry Smith 
175f4bdf6c4SBarry Smith   /*
176f4bdf6c4SBarry Smith        this is the Hack part where we monkey directly with the hypre datastructures
177f4bdf6c4SBarry Smith   */
178f4bdf6c4SBarry Smith   ierr = PetscMemcpy(hdiag->i,pdiag->i,(A->rmap->n + 1)*sizeof(PetscInt));
179f4bdf6c4SBarry Smith   ierr = PetscMemcpy(hdiag->j,pdiag->j,pdiag->nz*sizeof(PetscInt));
180f4bdf6c4SBarry Smith   ierr = PetscMemcpy(hdiag->data,pdiag->a,pdiag->nz*sizeof(PetscScalar));
181f4bdf6c4SBarry Smith 
182f4bdf6c4SBarry Smith   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
183*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_IJMatrixAssemble,(ij));
184f4bdf6c4SBarry Smith   ierr = PetscLogEventEnd(MAT_Convert,A,0,0,0);CHKERRQ(ierr);
185f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
186f4bdf6c4SBarry Smith }
187f4bdf6c4SBarry Smith 
188f4bdf6c4SBarry Smith #undef __FUNCT__
189f4bdf6c4SBarry Smith #define __FUNCT__ "MatHYPRE_IJMatrixFastCopy_MPIAIJ"
190f4bdf6c4SBarry Smith PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat A,HYPRE_IJMatrix ij)
191f4bdf6c4SBarry Smith {
192f4bdf6c4SBarry Smith   PetscErrorCode        ierr;
193f4bdf6c4SBarry Smith   Mat_MPIAIJ            *pA = (Mat_MPIAIJ*)A->data;
194f4bdf6c4SBarry Smith   Mat_SeqAIJ            *pdiag,*poffd;
195f4bdf6c4SBarry Smith   PetscInt              i,*garray = pA->garray,*jj,cstart,*pjj;
196f4bdf6c4SBarry Smith 
197f4bdf6c4SBarry Smith   hypre_ParCSRMatrix    *par_matrix;
198f4bdf6c4SBarry Smith   hypre_AuxParCSRMatrix *aux_matrix;
199f4bdf6c4SBarry Smith   hypre_CSRMatrix       *hdiag,*hoffd;
200f4bdf6c4SBarry Smith 
201f4bdf6c4SBarry Smith   PetscFunctionBegin;
202f4bdf6c4SBarry Smith   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
203f4bdf6c4SBarry Smith   PetscValidType(A,1);
204f4bdf6c4SBarry Smith   PetscValidPointer(ij,2);
205f4bdf6c4SBarry Smith   pdiag = (Mat_SeqAIJ*) pA->A->data;
206f4bdf6c4SBarry Smith   poffd = (Mat_SeqAIJ*) pA->B->data;
207f4bdf6c4SBarry Smith   /* cstart is only valid for square MPIAIJ layed out in the usual way */
208f4bdf6c4SBarry Smith   ierr = MatGetOwnershipRange(A,&cstart,PETSC_NULL);CHKERRQ(ierr);
209f4bdf6c4SBarry Smith 
210f4bdf6c4SBarry Smith   ierr = PetscLogEventBegin(MAT_Convert,A,0,0,0);CHKERRQ(ierr);
211*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij));
212f4bdf6c4SBarry Smith   par_matrix = (hypre_ParCSRMatrix*)hypre_IJMatrixObject(ij);
213f4bdf6c4SBarry Smith   aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
214f4bdf6c4SBarry Smith   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
215f4bdf6c4SBarry Smith   hoffd = hypre_ParCSRMatrixOffd(par_matrix);
216f4bdf6c4SBarry Smith 
217f4bdf6c4SBarry Smith   /*
218f4bdf6c4SBarry Smith        this is the Hack part where we monkey directly with the hypre datastructures
219f4bdf6c4SBarry Smith   */
220f4bdf6c4SBarry Smith   ierr = PetscMemcpy(hdiag->i,pdiag->i,(pA->A->rmap->n + 1)*sizeof(PetscInt));
221f4bdf6c4SBarry Smith   /* need to shift the diag column indices (hdiag->j) back to global numbering since hypre is expecting this */
222f4bdf6c4SBarry Smith   jj  = hdiag->j;
223f4bdf6c4SBarry Smith   pjj = pdiag->j;
224f4bdf6c4SBarry Smith   for (i=0; i<pdiag->nz; i++) {
225f4bdf6c4SBarry Smith     jj[i] = cstart + pjj[i];
226f4bdf6c4SBarry Smith   }
227f4bdf6c4SBarry Smith   ierr = PetscMemcpy(hdiag->data,pdiag->a,pdiag->nz*sizeof(PetscScalar));
228f4bdf6c4SBarry Smith   ierr = PetscMemcpy(hoffd->i,poffd->i,(pA->A->rmap->n + 1)*sizeof(PetscInt));
229f4bdf6c4SBarry Smith   /* need to move the offd column indices (hoffd->j) back to global numbering since hypre is expecting this
230f4bdf6c4SBarry Smith      If we hacked a hypre a bit more we might be able to avoid this step */
231f4bdf6c4SBarry Smith   jj  = hoffd->j;
232f4bdf6c4SBarry Smith   pjj = poffd->j;
233f4bdf6c4SBarry Smith   for (i=0; i<poffd->nz; i++) {
234f4bdf6c4SBarry Smith     jj[i] = garray[pjj[i]];
235f4bdf6c4SBarry Smith   }
236f4bdf6c4SBarry Smith   ierr = PetscMemcpy(hoffd->data,poffd->a,poffd->nz*sizeof(PetscScalar));
237f4bdf6c4SBarry Smith 
238f4bdf6c4SBarry Smith   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
239*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_IJMatrixAssemble,(ij));
240f4bdf6c4SBarry Smith   ierr = PetscLogEventEnd(MAT_Convert,A,0,0,0);CHKERRQ(ierr);
241f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
242f4bdf6c4SBarry Smith }
243f4bdf6c4SBarry Smith 
244f4bdf6c4SBarry Smith /*
245f4bdf6c4SBarry Smith     Does NOT copy the data over, instead uses DIRECTLY the pointers from the PETSc MPIAIJ format
246f4bdf6c4SBarry Smith 
247f4bdf6c4SBarry Smith     This is UNFINISHED and does NOT work! The problem is that hypre puts the diagonal entry first
248f4bdf6c4SBarry Smith     which will corrupt the PETSc data structure if we did this. Need a work around to this problem.
249f4bdf6c4SBarry Smith */
250c6db04a5SJed Brown #include <_hypre_IJ_mv.h>
251c6db04a5SJed Brown #include <HYPRE_IJ_mv.h>
252f4bdf6c4SBarry Smith 
253f4bdf6c4SBarry Smith #undef __FUNCT__
254f4bdf6c4SBarry Smith #define __FUNCT__ "MatHYPRE_IJMatrixLink"
255f4bdf6c4SBarry Smith PetscErrorCode MatHYPRE_IJMatrixLink(Mat A,HYPRE_IJMatrix *ij)
256f4bdf6c4SBarry Smith {
257f4bdf6c4SBarry Smith   PetscErrorCode        ierr;
2584ddd07fcSJed Brown   PetscInt              rstart,rend,cstart,cend;
259f4bdf6c4SBarry Smith   PetscBool             flg;
260f4bdf6c4SBarry Smith   hypre_AuxParCSRMatrix *aux_matrix;
261f4bdf6c4SBarry Smith 
262f4bdf6c4SBarry Smith   PetscFunctionBegin;
263f4bdf6c4SBarry Smith   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
264f4bdf6c4SBarry Smith   PetscValidType(A,1);
265f4bdf6c4SBarry Smith   PetscValidPointer(ij,2);
266251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&flg);CHKERRQ(ierr);
267f4bdf6c4SBarry Smith   if (!flg) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_SUP,"Can only use with PETSc MPIAIJ matrices");
2684994cf47SJed Brown   ierr = MatSetUp(A);CHKERRQ(ierr);
269f4bdf6c4SBarry Smith 
270f4bdf6c4SBarry Smith   ierr = PetscLogEventBegin(MAT_Convert,A,0,0,0);CHKERRQ(ierr);
271f4bdf6c4SBarry Smith   rstart = A->rmap->rstart;
272f4bdf6c4SBarry Smith   rend   = A->rmap->rend;
273f4bdf6c4SBarry Smith   cstart = A->cmap->rstart;
274f4bdf6c4SBarry Smith   cend   = A->cmap->rend;
275*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_IJMatrixCreate,(((PetscObject)A)->comm,rstart,rend-1,cstart,cend-1,ij));
276*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(*ij,HYPRE_PARCSR));
277f4bdf6c4SBarry Smith 
278*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(*ij));
279*fd3f9acdSBarry Smith   PetscStackCall("hypre_IJMatrixTranslator",aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(*ij));
280f4bdf6c4SBarry Smith 
281f4bdf6c4SBarry Smith   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
282f4bdf6c4SBarry Smith 
283f4bdf6c4SBarry Smith   /* this is the Hack part where we monkey directly with the hypre datastructures */
284f4bdf6c4SBarry Smith 
285*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_IJMatrixAssemble,(*ij));
286f4bdf6c4SBarry Smith   ierr = PetscLogEventEnd(MAT_Convert,A,0,0,0);CHKERRQ(ierr);
287f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
288f4bdf6c4SBarry Smith }
289f4bdf6c4SBarry Smith 
290f4bdf6c4SBarry Smith /* -----------------------------------------------------------------------------------------------------------------*/
291f4bdf6c4SBarry Smith 
292f4bdf6c4SBarry Smith /*MC
293f4bdf6c4SBarry Smith    MATHYPRESTRUCT - MATHYPRESTRUCT = "hyprestruct" - A matrix type to be used for parallel sparse matrices
294f4bdf6c4SBarry Smith           based on the hypre HYPRE_StructMatrix.
295f4bdf6c4SBarry Smith 
296f4bdf6c4SBarry Smith    Level: intermediate
297f4bdf6c4SBarry Smith 
298f4bdf6c4SBarry Smith    Notes: Unlike the more general support for blocks in hypre this allows only one block per process and requires the block
299f4bdf6c4SBarry Smith           be defined by a DMDA.
300f4bdf6c4SBarry Smith 
301c688c046SMatthew G Knepley           The matrix needs a DMDA associated with it by either a call to MatSetupDM() or if the matrix is obtained from DMCreateMatrix()
302f4bdf6c4SBarry Smith 
303c688c046SMatthew G Knepley .seealso: MatCreate(), PCPFMG, MatSetupDM(), DMCreateMatrix()
304f4bdf6c4SBarry Smith M*/
305f4bdf6c4SBarry Smith 
306f4bdf6c4SBarry Smith 
307f4bdf6c4SBarry Smith #undef __FUNCT__
308f4bdf6c4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_HYPREStruct_3d"
309f4bdf6c4SBarry Smith PetscErrorCode  MatSetValuesLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
310f4bdf6c4SBarry Smith {
311f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
312f4bdf6c4SBarry Smith   PetscInt          i,j,stencil,index[3],row,entries[7];
313f4bdf6c4SBarry Smith   const PetscScalar *values = y;
314f4bdf6c4SBarry Smith   Mat_HYPREStruct   *ex = (Mat_HYPREStruct*) mat->data;
315f4bdf6c4SBarry Smith 
316f4bdf6c4SBarry Smith   PetscFunctionBegin;
317f4bdf6c4SBarry Smith   for (i=0; i<nrow; i++) {
318f4bdf6c4SBarry Smith     for (j=0; j<ncol; j++) {
319f4bdf6c4SBarry Smith       stencil = icol[j] - irow[i];
320f4bdf6c4SBarry Smith       if (!stencil) {
321f4bdf6c4SBarry Smith         entries[j] = 3;
322f4bdf6c4SBarry Smith       } else if (stencil == -1) {
323f4bdf6c4SBarry Smith         entries[j] = 2;
324f4bdf6c4SBarry Smith       } else if (stencil == 1) {
325f4bdf6c4SBarry Smith         entries[j] = 4;
326f4bdf6c4SBarry Smith       } else if (stencil == -ex->gnx) {
327f4bdf6c4SBarry Smith         entries[j] = 1;
328f4bdf6c4SBarry Smith       } else if (stencil == ex->gnx) {
329f4bdf6c4SBarry Smith         entries[j] = 5;
330f4bdf6c4SBarry Smith       } else if (stencil == -ex->gnxgny) {
331f4bdf6c4SBarry Smith         entries[j] = 0;
332f4bdf6c4SBarry Smith       } else if (stencil == ex->gnxgny) {
333f4bdf6c4SBarry Smith         entries[j] = 6;
334f4bdf6c4SBarry Smith       } else SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
335f4bdf6c4SBarry Smith     }
336f4bdf6c4SBarry Smith     row = ex->gindices[irow[i]] - ex->rstart;
337f4bdf6c4SBarry Smith     index[0] = ex->xs + (row % ex->nx);
338f4bdf6c4SBarry Smith     index[1] = ex->ys + ((row/ex->nx) % ex->ny);
339f4bdf6c4SBarry Smith     index[2] = ex->zs + (row/(ex->nxny));
340f4bdf6c4SBarry Smith     if (addv == ADD_VALUES) {
341*fd3f9acdSBarry Smith       PetscStackCallStandard(HYPRE_StructMatrixAddToValues,(ex->hmat,index,ncol,entries,(PetscScalar*)values));
342f4bdf6c4SBarry Smith     } else {
343*fd3f9acdSBarry Smith       PetscStackCallStandard(HYPRE_StructMatrixSetValues,(ex->hmat,index,ncol,entries,(PetscScalar*)values));
344f4bdf6c4SBarry Smith     }
345f4bdf6c4SBarry Smith     values += ncol;
346f4bdf6c4SBarry Smith   }
347f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
348f4bdf6c4SBarry Smith }
349f4bdf6c4SBarry Smith 
350f4bdf6c4SBarry Smith #undef __FUNCT__
351f4bdf6c4SBarry Smith #define __FUNCT__ "MatZeroRowsLocal_HYPREStruct_3d"
352f4bdf6c4SBarry Smith PetscErrorCode  MatZeroRowsLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)
353f4bdf6c4SBarry Smith {
354f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
355f4bdf6c4SBarry Smith   PetscInt          i,index[3],row,entries[7] = {0,1,2,3,4,5,6};
356f4bdf6c4SBarry Smith   PetscScalar       values[7];
357f4bdf6c4SBarry Smith   Mat_HYPREStruct   *ex = (Mat_HYPREStruct*) mat->data;
358f4bdf6c4SBarry Smith 
359f4bdf6c4SBarry Smith   PetscFunctionBegin;
360f4bdf6c4SBarry Smith   if (x && b) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_SUP,"No support");
361f4bdf6c4SBarry Smith   ierr = PetscMemzero(values,7*sizeof(PetscScalar));CHKERRQ(ierr);
362f4bdf6c4SBarry Smith   values[3] = d;
363f4bdf6c4SBarry Smith   for (i=0; i<nrow; i++) {
364f4bdf6c4SBarry Smith     row = ex->gindices[irow[i]] - ex->rstart;
365f4bdf6c4SBarry Smith     index[0] = ex->xs + (row % ex->nx);
366f4bdf6c4SBarry Smith     index[1] = ex->ys + ((row/ex->nx) % ex->ny);
367f4bdf6c4SBarry Smith     index[2] = ex->zs + (row/(ex->nxny));
368*fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructMatrixSetValues,(ex->hmat,index,7,entries,values));
369f4bdf6c4SBarry Smith   }
370*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat));
371f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
372f4bdf6c4SBarry Smith }
373f4bdf6c4SBarry Smith 
374f4bdf6c4SBarry Smith #undef __FUNCT__
375f4bdf6c4SBarry Smith #define __FUNCT__ "MatZeroEntries_HYPREStruct_3d"
376f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct_3d(Mat mat)
377f4bdf6c4SBarry Smith {
378f4bdf6c4SBarry Smith   PetscErrorCode ierr;
379f4bdf6c4SBarry Smith   PetscInt       indices[7] = {0,1,2,3,4,5,6};
380f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
381f4bdf6c4SBarry Smith 
382f4bdf6c4SBarry Smith   PetscFunctionBegin;
383f4bdf6c4SBarry Smith   /* hypre has no public interface to do this */
384*fd3f9acdSBarry Smith   PetscStackCallStandard(hypre_StructMatrixClearBoxValues,(ex->hmat,&ex->hbox,7,indices,0,1));
385*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat));
386f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
387f4bdf6c4SBarry Smith }
388f4bdf6c4SBarry Smith 
389f4bdf6c4SBarry Smith #undef __FUNCT__
390c688c046SMatthew G Knepley #define __FUNCT__ "MatSetupDM_HYPREStruct"
391c688c046SMatthew G Knepley PetscErrorCode  MatSetupDM_HYPREStruct(Mat mat,DM da)
392f4bdf6c4SBarry Smith {
393f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
394f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
3954ddd07fcSJed Brown   PetscInt         dim,dof,sw[3],nx,ny,nz,ilower[3],iupper[3],ssize,i;
3967ab44359SJed Brown   DMDABoundaryType px,py,pz;
397f4bdf6c4SBarry Smith   DMDAStencilType  st;
398f4bdf6c4SBarry Smith 
399f4bdf6c4SBarry Smith   PetscFunctionBegin;
400f4bdf6c4SBarry Smith   ex->da = da;
401f4bdf6c4SBarry Smith   ierr   = PetscObjectReference((PetscObject)da);CHKERRQ(ierr);
402f4bdf6c4SBarry Smith 
4037ab44359SJed Brown   ierr = DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&px,&py,&pz,&st);CHKERRQ(ierr);
404f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
405f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
406f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
407f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
408f4bdf6c4SBarry Smith 
409f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
410f4bdf6c4SBarry Smith   ex->hbox.imin[0] = ilower[0];
411f4bdf6c4SBarry Smith   ex->hbox.imin[1] = ilower[1];
412f4bdf6c4SBarry Smith   ex->hbox.imin[2] = ilower[2];
413f4bdf6c4SBarry Smith   ex->hbox.imax[0] = iupper[0];
414f4bdf6c4SBarry Smith   ex->hbox.imax[1] = iupper[1];
415f4bdf6c4SBarry Smith   ex->hbox.imax[2] = iupper[2];
416f4bdf6c4SBarry Smith 
417f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
418f4bdf6c4SBarry Smith   if (dof > 1) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Currently only support for scalar problems");
4197ab44359SJed Brown   if (px || py || pz) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_StructGridSetPeriodic()");
420*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridCreate,(ex->hcomm,dim,&ex->hgrid));
421*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridSetExtents,(ex->hgrid,ilower,iupper));
422*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridAssemble,(ex->hgrid));
423f4bdf6c4SBarry Smith 
424f4bdf6c4SBarry Smith   sw[1] = sw[0];
425f4bdf6c4SBarry Smith   sw[2] = sw[1];
426*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridSetNumGhost,(ex->hgrid,sw));
427f4bdf6c4SBarry Smith 
428f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
429f4bdf6c4SBarry Smith   if (sw[0] > 1) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Ask us to add support for wider stencils");
430f4bdf6c4SBarry Smith   if (st == DMDA_STENCIL_BOX) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Ask us to add support for box stencils");
431f4bdf6c4SBarry Smith   if (dim == 1) {
4324ddd07fcSJed Brown     PetscInt offsets[3][1] = {{-1},{0},{1}};
433f4bdf6c4SBarry Smith     ssize = 3;
434*fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
435f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
436*fd3f9acdSBarry Smith       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,offsets[i]));
437f4bdf6c4SBarry Smith     }
438f4bdf6c4SBarry Smith   } else if (dim == 2) {
4394ddd07fcSJed Brown     PetscInt offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
440f4bdf6c4SBarry Smith     ssize = 5;
441*fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
442f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
443*fd3f9acdSBarry Smith       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,offsets[i]));
444f4bdf6c4SBarry Smith     }
445f4bdf6c4SBarry Smith   } else if (dim == 3) {
4464ddd07fcSJed Brown     PetscInt offsets[7][3] = {{0,0,-1},{0,-1,0},{-1,0,0},{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
447f4bdf6c4SBarry Smith     ssize = 7;
448*fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
449f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
450*fd3f9acdSBarry Smith       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,offsets[i]));
451f4bdf6c4SBarry Smith     }
452f4bdf6c4SBarry Smith   }
453f4bdf6c4SBarry Smith 
454f4bdf6c4SBarry Smith   /* create the HYPRE vector for rhs and solution */
455*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorCreate,(ex->hcomm,ex->hgrid,&ex->hb));
456*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorCreate,(ex->hcomm,ex->hgrid,&ex->hx));
457*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorInitialize,(ex->hb));
458*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorInitialize,(ex->hx));
459*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(ex->hb));
460*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(ex->hx));
461f4bdf6c4SBarry Smith 
462f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
463*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixCreate,(ex->hcomm,ex->hgrid,ex->hstencil,&ex->hmat));
464*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridDestroy,(ex->hgrid));
465*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructStencilDestroy,(ex->hstencil));
466f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
467*fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructMatrixInitialize,(ex->hmat));
468f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
469f4bdf6c4SBarry Smith   }
470f4bdf6c4SBarry Smith 
471f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
472f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(da,0,0,0,&nx,&ny,&nz);CHKERRQ(ierr);
473f4bdf6c4SBarry Smith   ierr = MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
474f4bdf6c4SBarry Smith   ierr = PetscLayoutSetBlockSize(mat->rmap,1);CHKERRQ(ierr);
475f4bdf6c4SBarry Smith   ierr = PetscLayoutSetBlockSize(mat->cmap,1);CHKERRQ(ierr);
476f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
477f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
478f4bdf6c4SBarry Smith 
479f4bdf6c4SBarry Smith   if (dim == 3) {
480f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPREStruct_3d;
481f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPREStruct_3d;
482f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPREStruct_3d;
483f4bdf6c4SBarry Smith     ierr = MatZeroEntries_HYPREStruct_3d(mat);CHKERRQ(ierr);
484f4bdf6c4SBarry Smith   } else SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Only support for 3d DMDA currently");
485f4bdf6c4SBarry Smith 
486f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
487f4bdf6c4SBarry Smith   ierr = MatGetOwnershipRange(mat,&ex->rstart,PETSC_NULL);CHKERRQ(ierr);
488f4bdf6c4SBarry Smith   ierr = DMDAGetGlobalIndices(ex->da,PETSC_NULL,&ex->gindices);CHKERRQ(ierr);
489f4bdf6c4SBarry Smith   ierr = DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,0);CHKERRQ(ierr);
490f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
491f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,0);CHKERRQ(ierr);
492f4bdf6c4SBarry Smith   ex->nxny = ex->nx*ex->ny;
493f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
494f4bdf6c4SBarry Smith }
495f4bdf6c4SBarry Smith 
496f4bdf6c4SBarry Smith #undef __FUNCT__
497f4bdf6c4SBarry Smith #define __FUNCT__ "MatMult_HYPREStruct"
498f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPREStruct(Mat A,Vec x,Vec y)
499f4bdf6c4SBarry Smith {
500f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
501f4bdf6c4SBarry Smith   PetscScalar     *xx,*yy;
5024ddd07fcSJed Brown   PetscInt        ilower[3],iupper[3];
503f4bdf6c4SBarry Smith   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(A->data);
504f4bdf6c4SBarry Smith 
505f4bdf6c4SBarry Smith   PetscFunctionBegin;
506f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
507f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
508f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
509f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
510f4bdf6c4SBarry Smith 
511f4bdf6c4SBarry Smith   /* copy x values over to hypre */
512*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorSetConstantValues,(mx->hb,0.0));
513f4bdf6c4SBarry Smith   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
514*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorSetBoxValues,(mx->hb,ilower,iupper,xx));
515f4bdf6c4SBarry Smith   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
516*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(mx->hb));
517*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixMatvec,(1.0,mx->hmat,mx->hb,0.0,mx->hx));
518f4bdf6c4SBarry Smith 
519f4bdf6c4SBarry Smith   /* copy solution values back to PETSc */
520f4bdf6c4SBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
521*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorGetBoxValues,(mx->hx,ilower,iupper,yy));
522f4bdf6c4SBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
523f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
524f4bdf6c4SBarry Smith }
525f4bdf6c4SBarry Smith 
526f4bdf6c4SBarry Smith #undef __FUNCT__
527f4bdf6c4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_HYPREStruct"
528f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat,MatAssemblyType mode)
529f4bdf6c4SBarry Smith {
530f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
531f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
532f4bdf6c4SBarry Smith 
533f4bdf6c4SBarry Smith   PetscFunctionBegin;
534*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat));
535*fd3f9acdSBarry Smith   /* PetscStackCallStandard(HYPRE_StructMatrixPrint,("dummy",ex->hmat,0)); */
536f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
537f4bdf6c4SBarry Smith }
538f4bdf6c4SBarry Smith 
539f4bdf6c4SBarry Smith #undef __FUNCT__
540f4bdf6c4SBarry Smith #define __FUNCT__ "MatZeroEntries_HYPREStruct"
541f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat)
542f4bdf6c4SBarry Smith {
543f4bdf6c4SBarry Smith   PetscFunctionBegin;
544f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
545f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
546f4bdf6c4SBarry Smith }
547f4bdf6c4SBarry Smith 
548f4bdf6c4SBarry Smith 
549f4bdf6c4SBarry Smith #undef __FUNCT__
550f4bdf6c4SBarry Smith #define __FUNCT__ "MatDestroy_HYPREStruct"
551f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPREStruct(Mat mat)
552f4bdf6c4SBarry Smith {
553f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
554f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
555f4bdf6c4SBarry Smith 
556f4bdf6c4SBarry Smith   PetscFunctionBegin;
557*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixDestroy,(ex->hmat));
558*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorDestroy,(ex->hx));
559*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorDestroy,(ex->hb));
560f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
561f4bdf6c4SBarry Smith }
562f4bdf6c4SBarry Smith 
563f4bdf6c4SBarry Smith 
564f4bdf6c4SBarry Smith EXTERN_C_BEGIN
565f4bdf6c4SBarry Smith #undef __FUNCT__
566f4bdf6c4SBarry Smith #define __FUNCT__ "MatCreate_HYPREStruct"
567f4bdf6c4SBarry Smith PetscErrorCode  MatCreate_HYPREStruct(Mat B)
568f4bdf6c4SBarry Smith {
569f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex;
570f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
571f4bdf6c4SBarry Smith 
572f4bdf6c4SBarry Smith   PetscFunctionBegin;
573f4bdf6c4SBarry Smith   ierr            = PetscNewLog(B,Mat_HYPREStruct,&ex);CHKERRQ(ierr);
574f4bdf6c4SBarry Smith   B->data         = (void*)ex;
575f4bdf6c4SBarry Smith   B->rmap->bs     = 1;
576f4bdf6c4SBarry Smith   B->assembled    = PETSC_FALSE;
577f4bdf6c4SBarry Smith 
578f4bdf6c4SBarry Smith   B->insertmode   = NOT_SET_VALUES;
579f4bdf6c4SBarry Smith 
580f4bdf6c4SBarry Smith   B->ops->assemblyend    = MatAssemblyEnd_HYPREStruct;
581f4bdf6c4SBarry Smith   B->ops->mult           = MatMult_HYPREStruct;
582f4bdf6c4SBarry Smith   B->ops->zeroentries    = MatZeroEntries_HYPREStruct;
583f4bdf6c4SBarry Smith   B->ops->destroy        = MatDestroy_HYPREStruct;
584f4bdf6c4SBarry Smith 
585f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
586f4bdf6c4SBarry Smith 
587f4bdf6c4SBarry Smith   ierr = MPI_Comm_dup(((PetscObject)B)->comm,&(ex->hcomm));CHKERRQ(ierr);
588c688c046SMatthew G Knepley   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSetupDM_C","MatSetupDM_HYPREStruct",MatSetupDM_HYPREStruct);CHKERRQ(ierr);
589f4bdf6c4SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRESTRUCT);CHKERRQ(ierr);
590f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
591f4bdf6c4SBarry Smith }
592f4bdf6c4SBarry Smith EXTERN_C_END
593f4bdf6c4SBarry Smith 
594f4bdf6c4SBarry Smith 
595f4bdf6c4SBarry Smith /*MC
596f4bdf6c4SBarry Smith    MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices
597f4bdf6c4SBarry Smith           based on the hypre HYPRE_SStructMatrix.
598f4bdf6c4SBarry Smith 
599f4bdf6c4SBarry Smith 
600f4bdf6c4SBarry Smith    Level: intermediate
601f4bdf6c4SBarry Smith 
602f4bdf6c4SBarry Smith    Notes: Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured
603f4bdf6c4SBarry Smith           grid objects, we will restrict the semi-struct objects to consist of only structured-grid components.
604f4bdf6c4SBarry Smith 
605f4bdf6c4SBarry Smith           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
606f4bdf6c4SBarry Smith           be defined by a DMDA.
607f4bdf6c4SBarry Smith 
608c688c046SMatthew G Knepley           The matrix needs a DMDA associated with it by either a call to MatSetupDM() or if the matrix is obtained from DMCreateMatrix()
609f4bdf6c4SBarry Smith 
610f4bdf6c4SBarry Smith M*/
611f4bdf6c4SBarry Smith 
612f4bdf6c4SBarry Smith #undef __FUNCT__
613f4bdf6c4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_HYPRESStruct_3d"
614f4bdf6c4SBarry Smith PetscErrorCode  MatSetValuesLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
615f4bdf6c4SBarry Smith {
616f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
617f4bdf6c4SBarry Smith   PetscInt          i,j,stencil,index[3];
618f4bdf6c4SBarry Smith   const PetscScalar *values = y;
619f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *ex = (Mat_HYPRESStruct*) mat->data;
620f4bdf6c4SBarry Smith 
6214ddd07fcSJed Brown   PetscInt          part= 0; /* Petsc sstruct interface only allows 1 part */
6224ddd07fcSJed Brown   PetscInt          ordering;
6234ddd07fcSJed Brown   PetscInt          grid_rank, to_grid_rank;
6244ddd07fcSJed Brown   PetscInt          var_type, to_var_type;
6254ddd07fcSJed Brown   PetscInt          to_var_entry = 0;
626f4bdf6c4SBarry Smith 
6274ddd07fcSJed Brown   PetscInt          nvars= ex->nvars;
628f4bdf6c4SBarry Smith   PetscInt          row,*entries;
629f4bdf6c4SBarry Smith 
630f4bdf6c4SBarry Smith   PetscFunctionBegin;
631f4bdf6c4SBarry Smith   ierr = PetscMalloc(7*nvars*sizeof(PetscInt),&entries);CHKERRQ(ierr);
632f4bdf6c4SBarry Smith   ordering= ex-> dofs_order; /* ordering= 0   nodal ordering
633f4bdf6c4SBarry Smith                                           1   variable ordering */
634f4bdf6c4SBarry Smith   /* stencil entries are orderer by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ...  */
635f4bdf6c4SBarry Smith 
636f4bdf6c4SBarry Smith   if (!ordering) {
637f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
638f4bdf6c4SBarry Smith       grid_rank= irow[i]/nvars;
639f4bdf6c4SBarry Smith       var_type = (irow[i] % nvars);
640f4bdf6c4SBarry Smith 
641f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
642f4bdf6c4SBarry Smith         to_grid_rank= icol[j]/nvars;
643f4bdf6c4SBarry Smith         to_var_type = (icol[j] % nvars);
644f4bdf6c4SBarry Smith 
645f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
646f4bdf6c4SBarry Smith         entries[j]= to_var_entry;
647f4bdf6c4SBarry Smith 
648f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
649f4bdf6c4SBarry Smith         if (!stencil) {
650f4bdf6c4SBarry Smith           entries[j] += 3;
651f4bdf6c4SBarry Smith         } else if (stencil == -1) {
652f4bdf6c4SBarry Smith           entries[j] += 2;
653f4bdf6c4SBarry Smith         } else if (stencil == 1) {
654f4bdf6c4SBarry Smith           entries[j] += 4;
655f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
656f4bdf6c4SBarry Smith           entries[j] += 1;
657f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
658f4bdf6c4SBarry Smith           entries[j] += 5;
659f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
660f4bdf6c4SBarry Smith           entries[j] += 0;
661f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
662f4bdf6c4SBarry Smith           entries[j] += 6;
663f4bdf6c4SBarry Smith         } else SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
664f4bdf6c4SBarry Smith       }
665f4bdf6c4SBarry Smith 
666f4bdf6c4SBarry Smith       row = ex->gindices[grid_rank] - ex->rstart;
667f4bdf6c4SBarry Smith       index[0] = ex->xs + (row % ex->nx);
668f4bdf6c4SBarry Smith       index[1] = ex->ys + ((row/ex->nx) % ex->ny);
669f4bdf6c4SBarry Smith       index[2] = ex->zs + (row/(ex->nxny));
670f4bdf6c4SBarry Smith 
671f4bdf6c4SBarry Smith       if (addv == ADD_VALUES) {
672*fd3f9acdSBarry Smith         PetscStackCallStandard(HYPRE_SStructMatrixAddToValues,(ex->ss_mat,part,index,var_type,ncol,entries,(PetscScalar*)values));
673f4bdf6c4SBarry Smith       } else {
674*fd3f9acdSBarry Smith         PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,index,var_type,ncol,entries,(PetscScalar*)values));
675f4bdf6c4SBarry Smith       }
676f4bdf6c4SBarry Smith       values += ncol;
677f4bdf6c4SBarry Smith     }
678f4bdf6c4SBarry Smith   } else {
679f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
680f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
681f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
682f4bdf6c4SBarry Smith 
683f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
684f4bdf6c4SBarry Smith         to_var_type = icol[j]/(ex->gnxgnygnz);
685f4bdf6c4SBarry Smith         to_grid_rank= icol[j] - to_var_type*(ex->gnxgnygnz);
686f4bdf6c4SBarry Smith 
687f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
688f4bdf6c4SBarry Smith         entries[j]= to_var_entry;
689f4bdf6c4SBarry Smith 
690f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
691f4bdf6c4SBarry Smith         if (!stencil) {
692f4bdf6c4SBarry Smith           entries[j] += 3;
693f4bdf6c4SBarry Smith         } else if (stencil == -1) {
694f4bdf6c4SBarry Smith           entries[j] += 2;
695f4bdf6c4SBarry Smith         } else if (stencil == 1) {
696f4bdf6c4SBarry Smith           entries[j] += 4;
697f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
698f4bdf6c4SBarry Smith           entries[j] += 1;
699f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
700f4bdf6c4SBarry Smith           entries[j] += 5;
701f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
702f4bdf6c4SBarry Smith           entries[j] += 0;
703f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
704f4bdf6c4SBarry Smith           entries[j] += 6;
705f4bdf6c4SBarry Smith         } else SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
706f4bdf6c4SBarry Smith       }
707f4bdf6c4SBarry Smith 
708f4bdf6c4SBarry Smith       row = ex->gindices[grid_rank] - ex->rstart;
709f4bdf6c4SBarry Smith       index[0] = ex->xs + (row % ex->nx);
710f4bdf6c4SBarry Smith       index[1] = ex->ys + ((row/ex->nx) % ex->ny);
711f4bdf6c4SBarry Smith       index[2] = ex->zs + (row/(ex->nxny));
712f4bdf6c4SBarry Smith 
713f4bdf6c4SBarry Smith       if (addv == ADD_VALUES) {
714*fd3f9acdSBarry Smith         PetscStackCallStandard(HYPRE_SStructMatrixAddToValues,(ex->ss_mat,part,index,var_type,ncol,entries,(PetscScalar*)values));
715f4bdf6c4SBarry Smith       } else {
716*fd3f9acdSBarry Smith         PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,index,var_type,ncol,entries,(PetscScalar*)values));
717f4bdf6c4SBarry Smith       }
718f4bdf6c4SBarry Smith       values += ncol;
719f4bdf6c4SBarry Smith     }
720f4bdf6c4SBarry Smith   }
721f4bdf6c4SBarry Smith   ierr = PetscFree(entries);CHKERRQ(ierr);
722f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
723f4bdf6c4SBarry Smith }
724f4bdf6c4SBarry Smith 
725f4bdf6c4SBarry Smith #undef __FUNCT__
726f4bdf6c4SBarry Smith #define __FUNCT__ "MatZeroRowsLocal_HYPRESStruct_3d"
727f4bdf6c4SBarry Smith PetscErrorCode  MatZeroRowsLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)
728f4bdf6c4SBarry Smith {
729f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
730f4bdf6c4SBarry Smith   PetscInt          i,index[3];
731f4bdf6c4SBarry Smith   PetscScalar     **values;
732f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
733f4bdf6c4SBarry Smith 
7344ddd07fcSJed Brown   PetscInt          part= 0; /* Petsc sstruct interface only allows 1 part */
7354ddd07fcSJed Brown   PetscInt          ordering= ex->dofs_order;
7364ddd07fcSJed Brown   PetscInt          grid_rank;
7374ddd07fcSJed Brown   PetscInt          var_type;
7384ddd07fcSJed Brown   PetscInt          nvars= ex->nvars;
739f4bdf6c4SBarry Smith   PetscInt          row,*entries;
740f4bdf6c4SBarry Smith 
741f4bdf6c4SBarry Smith   PetscFunctionBegin;
742f4bdf6c4SBarry Smith   if (x && b) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_SUP,"No support");
743f4bdf6c4SBarry Smith   ierr = PetscMalloc(7*nvars*sizeof(PetscInt),&entries);CHKERRQ(ierr);
744f4bdf6c4SBarry Smith 
745f4bdf6c4SBarry Smith   ierr = PetscMalloc(nvars*sizeof(PetscScalar *),&values);CHKERRQ(ierr);
746f4bdf6c4SBarry Smith   ierr = PetscMalloc(7*nvars*nvars*sizeof(PetscScalar),&values[0]);CHKERRQ(ierr);
747f4bdf6c4SBarry Smith   for (i=1; i<nvars; i++) {
748f4bdf6c4SBarry Smith      values[i] = values[i-1] + nvars*7;
749f4bdf6c4SBarry Smith   }
750f4bdf6c4SBarry Smith 
751f4bdf6c4SBarry Smith   for (i=0; i< nvars; i++) {
752f4bdf6c4SBarry Smith     ierr = PetscMemzero(values[i],nvars*7*sizeof(PetscScalar));CHKERRQ(ierr);
753f4bdf6c4SBarry Smith     *(values[i]+3)= d;
754f4bdf6c4SBarry Smith   }
755f4bdf6c4SBarry Smith 
756f4bdf6c4SBarry Smith   for (i= 0; i< nvars*7; i++) {
757f4bdf6c4SBarry Smith     entries[i]= i;
758f4bdf6c4SBarry Smith   }
759f4bdf6c4SBarry Smith 
760f4bdf6c4SBarry Smith   if (!ordering) {
761f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
762f4bdf6c4SBarry Smith        grid_rank= irow[i]/nvars;
763f4bdf6c4SBarry Smith        var_type = (irow[i] % nvars);
764f4bdf6c4SBarry Smith 
765f4bdf6c4SBarry Smith        row = ex->gindices[grid_rank] - ex->rstart;
766f4bdf6c4SBarry Smith        index[0] = ex->xs + (row % ex->nx);
767f4bdf6c4SBarry Smith        index[1] = ex->ys + ((row/ex->nx) % ex->ny);
768f4bdf6c4SBarry Smith        index[2] = ex->zs + (row/(ex->nxny));
769*fd3f9acdSBarry Smith        PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,index,var_type,7*nvars,entries,values[var_type]));
770f4bdf6c4SBarry Smith     }
771f4bdf6c4SBarry Smith   } else {
772f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
773f4bdf6c4SBarry Smith        var_type = irow[i]/(ex->gnxgnygnz);
774f4bdf6c4SBarry Smith        grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
775f4bdf6c4SBarry Smith 
776f4bdf6c4SBarry Smith        row = ex->gindices[grid_rank] - ex->rstart;
777f4bdf6c4SBarry Smith        index[0] = ex->xs + (row % ex->nx);
778f4bdf6c4SBarry Smith        index[1] = ex->ys + ((row/ex->nx) % ex->ny);
779f4bdf6c4SBarry Smith        index[2] = ex->zs + (row/(ex->nxny));
780*fd3f9acdSBarry Smith        PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,index,var_type,7*nvars,entries,values[var_type]));
781f4bdf6c4SBarry Smith     }
782f4bdf6c4SBarry Smith   }
783*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
784f4bdf6c4SBarry Smith   ierr = PetscFree(values[0]);CHKERRQ(ierr);
785f4bdf6c4SBarry Smith   ierr = PetscFree(values);CHKERRQ(ierr);
786f4bdf6c4SBarry Smith   ierr = PetscFree(entries);CHKERRQ(ierr);
787f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
788f4bdf6c4SBarry Smith }
789f4bdf6c4SBarry Smith 
790f4bdf6c4SBarry Smith #undef __FUNCT__
791f4bdf6c4SBarry Smith #define __FUNCT__ "MatZeroEntries_HYPRESStruct_3d"
792f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat)
793f4bdf6c4SBarry Smith {
794f4bdf6c4SBarry Smith   PetscErrorCode     ierr;
795f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *ex = (Mat_HYPRESStruct*) mat->data;
7964ddd07fcSJed Brown   PetscInt           nvars= ex->nvars;
7974ddd07fcSJed Brown   PetscInt           size;
7984ddd07fcSJed Brown   PetscInt           part= 0; /* only one part */
799f4bdf6c4SBarry Smith 
800f4bdf6c4SBarry Smith   PetscFunctionBegin;
801f4bdf6c4SBarry Smith   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);
802f4bdf6c4SBarry Smith   {
8034ddd07fcSJed Brown      PetscInt         i,*entries,iupper[3],ilower[3];
804f4bdf6c4SBarry Smith      PetscScalar      *values;
8054ddd07fcSJed Brown 
806f4bdf6c4SBarry Smith 
807f4bdf6c4SBarry Smith      for (i= 0; i< 3; i++) {
808f4bdf6c4SBarry Smith         ilower[i]= ex->hbox.imin[i];
809f4bdf6c4SBarry Smith         iupper[i]= ex->hbox.imax[i];
810f4bdf6c4SBarry Smith      }
811f4bdf6c4SBarry Smith 
812f4bdf6c4SBarry Smith      ierr = PetscMalloc2(nvars*7,PetscInt,&entries,nvars*7*size,PetscScalar,&values);CHKERRQ(ierr);
813f4bdf6c4SBarry Smith      for (i= 0; i< nvars*7; i++) {
814f4bdf6c4SBarry Smith         entries[i]= i;
815f4bdf6c4SBarry Smith      }
816f4bdf6c4SBarry Smith      ierr = PetscMemzero(values,nvars*7*size*sizeof(PetscScalar));CHKERRQ(ierr);
817f4bdf6c4SBarry Smith 
818f4bdf6c4SBarry Smith      for (i= 0; i< nvars; i++) {
819*fd3f9acdSBarry Smith        PetscStackCallStandard(HYPRE_SStructMatrixSetBoxValues,(ex->ss_mat,part,ilower,iupper,i,nvars*7,entries,values));
820f4bdf6c4SBarry Smith      }
821f4bdf6c4SBarry Smith      ierr = PetscFree2(entries,values);CHKERRQ(ierr);
822f4bdf6c4SBarry Smith   }
823*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
824f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
825f4bdf6c4SBarry Smith }
826f4bdf6c4SBarry Smith 
827f4bdf6c4SBarry Smith 
828f4bdf6c4SBarry Smith #undef __FUNCT__
829c688c046SMatthew G Knepley #define __FUNCT__ "MatSetupDM_HYPRESStruct"
830c688c046SMatthew G Knepley PetscErrorCode  MatSetupDM_HYPRESStruct(Mat mat,DM da)
831f4bdf6c4SBarry Smith {
832f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
833f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
834f4bdf6c4SBarry Smith   PetscInt          dim,dof,sw[3],nx,ny,nz;
8354ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3],ssize,i;
8367ab44359SJed Brown   DMDABoundaryType  px,py,pz;
837f4bdf6c4SBarry Smith   DMDAStencilType   st;
8384ddd07fcSJed Brown   PetscInt          nparts= 1; /* assuming only one part */
8394ddd07fcSJed Brown   PetscInt          part  = 0;
840f4bdf6c4SBarry Smith 
841f4bdf6c4SBarry Smith   PetscFunctionBegin;
842f4bdf6c4SBarry Smith   ex->da = da;
843f4bdf6c4SBarry Smith   ierr   = PetscObjectReference((PetscObject)da);CHKERRQ(ierr);
844f4bdf6c4SBarry Smith 
8457ab44359SJed Brown   ierr = DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&px,&py,&pz,&st);CHKERRQ(ierr);
846f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
847f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
848f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
849f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
850f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
851f4bdf6c4SBarry Smith   ex->hbox.imin[0] = ilower[0];
852f4bdf6c4SBarry Smith   ex->hbox.imin[1] = ilower[1];
853f4bdf6c4SBarry Smith   ex->hbox.imin[2] = ilower[2];
854f4bdf6c4SBarry Smith   ex->hbox.imax[0] = iupper[0];
855f4bdf6c4SBarry Smith   ex->hbox.imax[1] = iupper[1];
856f4bdf6c4SBarry Smith   ex->hbox.imax[2] = iupper[2];
857f4bdf6c4SBarry Smith 
858f4bdf6c4SBarry Smith   ex->dofs_order   = 0;
859f4bdf6c4SBarry Smith 
860f4bdf6c4SBarry Smith   /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */
861f4bdf6c4SBarry Smith   ex->nvars= dof;
862f4bdf6c4SBarry Smith 
863f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
8647ab44359SJed Brown   if (px || py || pz) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()");
865*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridCreate,(ex->hcomm,dim,nparts,&ex->ss_grid));
866f4bdf6c4SBarry Smith 
867*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridSetExtents,(ex->ss_grid,part,ex->hbox.imin,ex->hbox.imax));
868f4bdf6c4SBarry Smith 
869f4bdf6c4SBarry Smith   {
870f4bdf6c4SBarry Smith     HYPRE_SStructVariable *vartypes;
871f4bdf6c4SBarry Smith     ierr = PetscMalloc(ex->nvars*sizeof(HYPRE_SStructVariable),&vartypes);CHKERRQ(ierr);
872f4bdf6c4SBarry Smith     for (i= 0; i< ex->nvars; i++) {
873f4bdf6c4SBarry Smith       vartypes[i]= HYPRE_SSTRUCT_VARIABLE_CELL;
874f4bdf6c4SBarry Smith     }
875*fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructGridSetVariables,(ex->ss_grid, part, ex->nvars,vartypes));
876f4bdf6c4SBarry Smith     ierr = PetscFree(vartypes);CHKERRQ(ierr);
877f4bdf6c4SBarry Smith   }
878*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridAssemble,(ex->ss_grid));
879f4bdf6c4SBarry Smith 
880f4bdf6c4SBarry Smith   sw[1] = sw[0];
881f4bdf6c4SBarry Smith   sw[2] = sw[1];
882*fd3f9acdSBarry Smith   /* PetscStackCallStandard(HYPRE_SStructGridSetNumGhost,(ex->ss_grid,sw)); */
883f4bdf6c4SBarry Smith 
884f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
885f4bdf6c4SBarry Smith   if (sw[0] > 1) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Ask us to add support for wider stencils");
886f4bdf6c4SBarry Smith   if (st == DMDA_STENCIL_BOX) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Ask us to add support for box stencils");
887f4bdf6c4SBarry Smith 
888f4bdf6c4SBarry Smith   if (dim == 1) {
8894ddd07fcSJed Brown     PetscInt offsets[3][1] = {{-1},{0},{1}};
8904ddd07fcSJed Brown     PetscInt j, cnt;
891f4bdf6c4SBarry Smith 
892f4bdf6c4SBarry Smith     ssize = 3*(ex->nvars);
893*fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
894f4bdf6c4SBarry Smith     cnt= 0;
895f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
896f4bdf6c4SBarry Smith        for (j= 0; j< 3; j++) {
897*fd3f9acdSBarry Smith          PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, offsets[j], i));
898f4bdf6c4SBarry Smith           cnt++;
899f4bdf6c4SBarry Smith        }
900f4bdf6c4SBarry Smith     }
901f4bdf6c4SBarry Smith   } else if (dim == 2) {
9024ddd07fcSJed Brown     PetscInt offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
9034ddd07fcSJed Brown     PetscInt j, cnt;
904f4bdf6c4SBarry Smith 
905f4bdf6c4SBarry Smith     ssize = 5*(ex->nvars);
906*fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
907f4bdf6c4SBarry Smith     cnt= 0;
908f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
909f4bdf6c4SBarry Smith        for (j= 0; j< 5; j++) {
910*fd3f9acdSBarry Smith          PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, offsets[j], i));
911f4bdf6c4SBarry Smith           cnt++;
912f4bdf6c4SBarry Smith        }
913f4bdf6c4SBarry Smith     }
914f4bdf6c4SBarry Smith   } else if (dim == 3) {
9154ddd07fcSJed Brown     PetscInt offsets[7][3] = {{0,0,-1},{0,-1,0},{-1,0,0},{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
9164ddd07fcSJed Brown     PetscInt j, cnt;
917f4bdf6c4SBarry Smith 
918f4bdf6c4SBarry Smith     ssize = 7*(ex->nvars);
919*fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
920f4bdf6c4SBarry Smith     cnt= 0;
921f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
922f4bdf6c4SBarry Smith        for (j= 0; j< 7; j++) {
923*fd3f9acdSBarry Smith          PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, offsets[j], i));
924f4bdf6c4SBarry Smith           cnt++;
925f4bdf6c4SBarry Smith        }
926f4bdf6c4SBarry Smith     }
927f4bdf6c4SBarry Smith   }
928f4bdf6c4SBarry Smith 
929f4bdf6c4SBarry Smith   /* create the HYPRE graph */
930*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphCreate,(ex->hcomm, ex->ss_grid, &(ex->ss_graph)));
931f4bdf6c4SBarry Smith 
932f4bdf6c4SBarry Smith   /* set the stencil graph. Note that each variable has the same graph. This means that each
933f4bdf6c4SBarry Smith      variable couples to all the other variable and with the same stencil pattern. */
934f4bdf6c4SBarry Smith   for (i= 0; i< (ex->nvars); i++) {
935*fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructGraphSetStencil,(ex->ss_graph,part,i,ex->ss_stencil));
936f4bdf6c4SBarry Smith   }
937*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphAssemble,(ex->ss_graph));
938f4bdf6c4SBarry Smith 
939f4bdf6c4SBarry Smith   /* create the HYPRE sstruct vectors for rhs and solution */
940*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorCreate,(ex->hcomm,ex->ss_grid,&ex->ss_b));
941*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorCreate,(ex->hcomm,ex->ss_grid,&ex->ss_x));
942*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorInitialize,(ex->ss_b));
943*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorInitialize,(ex->ss_x));
944*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorAssemble,(ex->ss_b));
945*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorAssemble,(ex->ss_x));
946f4bdf6c4SBarry Smith 
947f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
948*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixCreate,(ex->hcomm,ex->ss_graph,&ex->ss_mat));
949*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridDestroy,(ex->ss_grid));
950*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructStencilDestroy,(ex->ss_stencil));
951f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
952*fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructMatrixInitialize,(ex->ss_mat));
953f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
954f4bdf6c4SBarry Smith   }
955f4bdf6c4SBarry Smith 
956f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
957f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(da,0,0,0,&nx,&ny,&nz);CHKERRQ(ierr);
958f4bdf6c4SBarry Smith   ierr = MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
959f4bdf6c4SBarry Smith   ierr = PetscLayoutSetBlockSize(mat->rmap,1);CHKERRQ(ierr);
960f4bdf6c4SBarry Smith   ierr = PetscLayoutSetBlockSize(mat->cmap,1);CHKERRQ(ierr);
961f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
962f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
963f4bdf6c4SBarry Smith 
964f4bdf6c4SBarry Smith   if (dim == 3) {
965f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d;
966f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPRESStruct_3d;
967f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPRESStruct_3d;
968f4bdf6c4SBarry Smith     ierr = MatZeroEntries_HYPRESStruct_3d(mat);CHKERRQ(ierr);
969f4bdf6c4SBarry Smith   } else SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Only support for 3d DMDA currently");
970f4bdf6c4SBarry Smith 
971f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
972f4bdf6c4SBarry Smith   ierr = MatGetOwnershipRange(mat,&ex->rstart,PETSC_NULL);CHKERRQ(ierr);
973f4bdf6c4SBarry Smith   ierr = DMDAGetGlobalIndices(ex->da,PETSC_NULL,&ex->gindices);CHKERRQ(ierr);
974f4bdf6c4SBarry Smith   ierr = DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,&ex->gnxgnygnz);CHKERRQ(ierr);
975f4bdf6c4SBarry Smith   ex->gnxgny    *= ex->gnx;
976f4bdf6c4SBarry Smith   ex->gnxgnygnz *= ex->gnxgny;
977f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,&ex->nz);CHKERRQ(ierr);
978f4bdf6c4SBarry Smith   ex->nxny   = ex->nx*ex->ny;
979f4bdf6c4SBarry Smith   ex->nxnynz = ex->nz*ex->nxny;
980f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
981f4bdf6c4SBarry Smith }
982f4bdf6c4SBarry Smith 
983f4bdf6c4SBarry Smith #undef __FUNCT__
984f4bdf6c4SBarry Smith #define __FUNCT__ "MatMult_HYPRESStruct"
985f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPRESStruct(Mat A,Vec x,Vec y)
986f4bdf6c4SBarry Smith {
987f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
988f4bdf6c4SBarry Smith   PetscScalar      *xx,*yy;
9894ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
990f4bdf6c4SBarry Smith   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(A->data);
9914ddd07fcSJed Brown   PetscInt          ordering= mx->dofs_order;
9924ddd07fcSJed Brown   PetscInt          nvars= mx->nvars;
9934ddd07fcSJed Brown   PetscInt          part= 0;
9944ddd07fcSJed Brown   PetscInt          size;
9954ddd07fcSJed Brown   PetscInt          i;
996f4bdf6c4SBarry Smith 
997f4bdf6c4SBarry Smith   PetscFunctionBegin;
998f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
999f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
1000f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
1001f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
1002f4bdf6c4SBarry Smith 
1003f4bdf6c4SBarry Smith   size= 1;
1004f4bdf6c4SBarry Smith   for (i= 0; i< 3; i++) {
1005f4bdf6c4SBarry Smith      size*= (iupper[i]-ilower[i]+1);
1006f4bdf6c4SBarry Smith   }
1007f4bdf6c4SBarry Smith 
1008f4bdf6c4SBarry Smith   /* copy x values over to hypre for variable ordering */
1009f4bdf6c4SBarry Smith   if (ordering) {
1010*fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0));
1011f4bdf6c4SBarry Smith      ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
1012f4bdf6c4SBarry Smith      for (i= 0; i< nvars; i++) {
1013*fd3f9acdSBarry Smith        PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,ilower,iupper,i,xx+(size*i)));
1014f4bdf6c4SBarry Smith      }
1015f4bdf6c4SBarry Smith      ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
1016*fd3f9acdSBarry Smith      PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b));
1017*fd3f9acdSBarry Smith      PetscStackCallStandard(HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x));
1018f4bdf6c4SBarry Smith 
1019f4bdf6c4SBarry Smith      /* copy solution values back to PETSc */
1020f4bdf6c4SBarry Smith      ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
1021f4bdf6c4SBarry Smith      for (i= 0; i< nvars; i++) {
1022*fd3f9acdSBarry Smith        PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,ilower,iupper,i,yy+(size*i)));
1023f4bdf6c4SBarry Smith      }
1024f4bdf6c4SBarry Smith      ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
1025f4bdf6c4SBarry Smith   } else {      /* nodal ordering must be mapped to variable ordering for sys_pfmg */
1026f4bdf6c4SBarry Smith      PetscScalar     *z;
10274ddd07fcSJed Brown      PetscInt         j, k;
1028f4bdf6c4SBarry Smith 
1029f4bdf6c4SBarry Smith      ierr = PetscMalloc(nvars*size*sizeof(PetscScalar),&z);CHKERRQ(ierr);
1030*fd3f9acdSBarry Smith      PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0));
1031f4bdf6c4SBarry Smith      ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
1032f4bdf6c4SBarry Smith 
1033f4bdf6c4SBarry Smith      /* transform nodal to hypre's variable ordering for sys_pfmg */
1034f4bdf6c4SBarry Smith      for (i= 0; i< size; i++) {
1035f4bdf6c4SBarry Smith         k= i*nvars;
1036f4bdf6c4SBarry Smith         for (j= 0; j< nvars; j++) {
1037f4bdf6c4SBarry Smith            z[j*size+i]= xx[k+j];
1038f4bdf6c4SBarry Smith         }
1039f4bdf6c4SBarry Smith      }
1040f4bdf6c4SBarry Smith      for (i= 0; i< nvars; i++) {
1041*fd3f9acdSBarry Smith        PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,ilower,iupper,i,z+(size*i)));
1042f4bdf6c4SBarry Smith      }
1043f4bdf6c4SBarry Smith      ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
1044*fd3f9acdSBarry Smith      PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b));
1045*fd3f9acdSBarry Smith      PetscStackCallStandard(HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x));
1046f4bdf6c4SBarry Smith 
1047f4bdf6c4SBarry Smith      /* copy solution values back to PETSc */
1048f4bdf6c4SBarry Smith      ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
1049f4bdf6c4SBarry Smith      for (i= 0; i< nvars; i++) {
1050*fd3f9acdSBarry Smith        PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,ilower,iupper,i,z+(size*i)));
1051f4bdf6c4SBarry Smith      }
1052f4bdf6c4SBarry Smith      /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
1053f4bdf6c4SBarry Smith      for (i= 0; i< size; i++) {
1054f4bdf6c4SBarry Smith         k= i*nvars;
1055f4bdf6c4SBarry Smith         for (j= 0; j< nvars; j++) {
1056f4bdf6c4SBarry Smith            yy[k+j]= z[j*size+i];
1057f4bdf6c4SBarry Smith         }
1058f4bdf6c4SBarry Smith      }
1059f4bdf6c4SBarry Smith      ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
1060f4bdf6c4SBarry Smith      ierr = PetscFree(z);CHKERRQ(ierr);
1061f4bdf6c4SBarry Smith   }
1062f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
1063f4bdf6c4SBarry Smith }
1064f4bdf6c4SBarry Smith 
1065f4bdf6c4SBarry Smith #undef __FUNCT__
1066f4bdf6c4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_HYPRESStruct"
1067f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat,MatAssemblyType mode)
1068f4bdf6c4SBarry Smith {
1069f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
1070f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
1071f4bdf6c4SBarry Smith 
1072f4bdf6c4SBarry Smith   PetscFunctionBegin;
1073*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
1074f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
1075f4bdf6c4SBarry Smith }
1076f4bdf6c4SBarry Smith 
1077f4bdf6c4SBarry Smith #undef __FUNCT__
1078f4bdf6c4SBarry Smith #define __FUNCT__ "MatZeroEntries_HYPRESStruct"
1079f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat)
1080f4bdf6c4SBarry Smith {
1081f4bdf6c4SBarry Smith   PetscFunctionBegin;
1082f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
1083f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
1084f4bdf6c4SBarry Smith }
1085f4bdf6c4SBarry Smith 
1086f4bdf6c4SBarry Smith 
1087f4bdf6c4SBarry Smith #undef __FUNCT__
1088f4bdf6c4SBarry Smith #define __FUNCT__ "MatDestroy_HYPRESStruct"
1089f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPRESStruct(Mat mat)
1090f4bdf6c4SBarry Smith {
1091f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
1092f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
1093f4bdf6c4SBarry Smith 
1094f4bdf6c4SBarry Smith   PetscFunctionBegin;
1095*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphDestroy,(ex->ss_graph));
1096*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixDestroy,(ex->ss_mat));
1097*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorDestroy,(ex->ss_x));
1098*fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorDestroy,(ex->ss_b));
1099f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
1100f4bdf6c4SBarry Smith }
1101f4bdf6c4SBarry Smith 
1102f4bdf6c4SBarry Smith EXTERN_C_BEGIN
1103f4bdf6c4SBarry Smith #undef __FUNCT__
1104f4bdf6c4SBarry Smith #define __FUNCT__ "MatCreate_HYPRESStruct"
1105f4bdf6c4SBarry Smith PetscErrorCode  MatCreate_HYPRESStruct(Mat B)
1106f4bdf6c4SBarry Smith {
1107f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex;
1108f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
1109f4bdf6c4SBarry Smith 
1110f4bdf6c4SBarry Smith   PetscFunctionBegin;
1111f4bdf6c4SBarry Smith   ierr            = PetscNewLog(B,Mat_HYPRESStruct,&ex);CHKERRQ(ierr);
1112f4bdf6c4SBarry Smith   B->data         = (void*)ex;
1113f4bdf6c4SBarry Smith   B->rmap->bs     = 1;
1114f4bdf6c4SBarry Smith   B->assembled    = PETSC_FALSE;
1115f4bdf6c4SBarry Smith 
1116f4bdf6c4SBarry Smith   B->insertmode   = NOT_SET_VALUES;
1117f4bdf6c4SBarry Smith 
1118f4bdf6c4SBarry Smith   B->ops->assemblyend    = MatAssemblyEnd_HYPRESStruct;
1119f4bdf6c4SBarry Smith   B->ops->mult           = MatMult_HYPRESStruct;
1120f4bdf6c4SBarry Smith   B->ops->zeroentries    = MatZeroEntries_HYPRESStruct;
1121f4bdf6c4SBarry Smith   B->ops->destroy        = MatDestroy_HYPRESStruct;
1122f4bdf6c4SBarry Smith 
1123f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
1124f4bdf6c4SBarry Smith 
1125f4bdf6c4SBarry Smith   ierr = MPI_Comm_dup(((PetscObject)B)->comm,&(ex->hcomm));CHKERRQ(ierr);
1126c688c046SMatthew G Knepley   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSetupDM_C","MatSetupDM_HYPRESStruct",MatSetupDM_HYPRESStruct);CHKERRQ(ierr);
1127f4bdf6c4SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRESSTRUCT);CHKERRQ(ierr);
1128f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
1129f4bdf6c4SBarry Smith }
1130f4bdf6c4SBarry Smith EXTERN_C_END
1131f4bdf6c4SBarry Smith 
1132f4bdf6c4SBarry Smith 
1133f4bdf6c4SBarry Smith 
1134