xref: /petsc/src/dm/impls/moab/dmmbmg.cxx (revision 2417220e389f0bcc8af9ba1c792700cf5b5e8cb9)
1755f3dfbSVijay Mahadevan #include <petsc/private/dmmbimpl.h>
2b117cd09SVijay Mahadevan #include <petscdmmoab.h>
3b117cd09SVijay Mahadevan #include <MBTagConventions.hpp>
4b117cd09SVijay Mahadevan #include <moab/NestedRefine.hpp>
5b117cd09SVijay Mahadevan 
6b117cd09SVijay Mahadevan #undef __FUNCT__
7b117cd09SVijay Mahadevan #define __FUNCT__ "DMMoabGenerateHierarchy"
8b117cd09SVijay Mahadevan /*@
9b117cd09SVijay Mahadevan   DMMoabGenerateHierarchy - Generate a multi-level uniform refinement hierarchy
10b117cd09SVijay Mahadevan   by succesively refining a coarse mesh, already defined in the DM object
11b117cd09SVijay Mahadevan   provided by the user.
12b117cd09SVijay Mahadevan 
13b117cd09SVijay Mahadevan   Collective on MPI_Comm
14b117cd09SVijay Mahadevan 
15b117cd09SVijay Mahadevan   Input Parameter:
16b117cd09SVijay Mahadevan + dmb  - The DMMoab object
17b117cd09SVijay Mahadevan 
18b117cd09SVijay Mahadevan   Output Parameter:
19b117cd09SVijay Mahadevan + nlevels   - The number of levels of refinement needed to generate the hierarchy
20b117cd09SVijay Mahadevan . ldegrees  - The degree of refinement at each level in the hierarchy
21b117cd09SVijay Mahadevan 
22b117cd09SVijay Mahadevan   Level: beginner
23b117cd09SVijay Mahadevan 
24b117cd09SVijay Mahadevan .keywords: DMMoab, create, refinement
25b117cd09SVijay Mahadevan @*/
26b117cd09SVijay Mahadevan PetscErrorCode DMMoabGenerateHierarchy(DM dm, PetscInt nlevels, PetscInt *ldegrees)
27b117cd09SVijay Mahadevan {
28b117cd09SVijay Mahadevan   DM_Moab        *dmmoab;
29b117cd09SVijay Mahadevan   PetscErrorCode  ierr;
30b117cd09SVijay Mahadevan   moab::ErrorCode merr;
31*2417220eSVijay Mahadevan   PetscInt *pdegrees, ilevel;
32e882eb38SVijay Mahadevan   std::vector<moab::EntityHandle> hsets;
33b117cd09SVijay Mahadevan 
34b117cd09SVijay Mahadevan   PetscFunctionBegin;
35b117cd09SVijay Mahadevan   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36b117cd09SVijay Mahadevan   dmmoab = (DM_Moab*)(dm)->data;
37b117cd09SVijay Mahadevan 
38b117cd09SVijay Mahadevan   if (!ldegrees) {
39b117cd09SVijay Mahadevan     ierr = PetscMalloc1(nlevels, &pdegrees);CHKERRQ(ierr);
40*2417220eSVijay Mahadevan     for (ilevel = 0; ilevel < nlevels; ilevel++) pdegrees[ilevel] = 2; /* default = Degree 2 refinement */
41b117cd09SVijay Mahadevan   }
42b117cd09SVijay Mahadevan   else pdegrees = ldegrees;
43b117cd09SVijay Mahadevan 
44b117cd09SVijay Mahadevan   /* initialize set level refinement data for hierarchy */
45b117cd09SVijay Mahadevan   dmmoab->nhlevels = nlevels;
46b117cd09SVijay Mahadevan 
47b117cd09SVijay Mahadevan   /* Instantiate the nested refinement class */
489daf19fdSVijay Mahadevan #ifdef MOAB_HAVE_MPI
493f1c6e43SVijay Mahadevan   dmmoab->hierarchy = new moab::NestedRefine(dynamic_cast<moab::Core*>(dmmoab->mbiface), dmmoab->pcomm, dmmoab->fileset);
509daf19fdSVijay Mahadevan #else
519daf19fdSVijay Mahadevan   dmmoab->hierarchy = new moab::NestedRefine(dynamic_cast<moab::Core*>(dmmoab->mbiface), NULL, dmmoab->fileset);
529daf19fdSVijay Mahadevan #endif
53b117cd09SVijay Mahadevan 
54e882eb38SVijay Mahadevan   ierr = PetscMalloc1(nlevels + 1, &dmmoab->hsets);CHKERRQ(ierr);
55e882eb38SVijay Mahadevan 
56b117cd09SVijay Mahadevan   /* generate the mesh hierarchy */
5764e1c140SVijay Mahadevan   merr = dmmoab->hierarchy->generate_mesh_hierarchy(nlevels, pdegrees, hsets);MBERRNM(merr);
58e882eb38SVijay Mahadevan 
599daf19fdSVijay Mahadevan #ifdef MOAB_HAVE_MPI
60755f3dfbSVijay Mahadevan   if (dmmoab->pcomm->size() > 1) {
6164e1c140SVijay Mahadevan     merr = dmmoab->hierarchy->exchange_ghosts(hsets, dmmoab->nghostrings);MBERRNM(merr);
62755f3dfbSVijay Mahadevan   }
639daf19fdSVijay Mahadevan #endif
6449d66b22SVijay Mahadevan 
6564e1c140SVijay Mahadevan   /* copy the mesh sets for nested refinement hierarchy */
66*2417220eSVijay Mahadevan   for (ilevel = 0; ilevel <= nlevels; ilevel++)
67*2417220eSVijay Mahadevan   {
68*2417220eSVijay Mahadevan     if (ilevel) { /* Update material and other geometric tags from parent to child sets */
69*2417220eSVijay Mahadevan       merr = dmmoab->hierarchy->update_special_tags(ilevel, hsets[ilevel]);MBERRNM(merr);
70*2417220eSVijay Mahadevan     }
71*2417220eSVijay Mahadevan 
72*2417220eSVijay Mahadevan     dmmoab->hsets[ilevel] = hsets[ilevel];
73*2417220eSVijay Mahadevan   }
7464e1c140SVijay Mahadevan 
7564e1c140SVijay Mahadevan   hsets.clear();
76b117cd09SVijay Mahadevan   if (!ldegrees) {
77b117cd09SVijay Mahadevan     ierr = PetscFree(pdegrees);CHKERRQ(ierr);
78b117cd09SVijay Mahadevan   }
79b117cd09SVijay Mahadevan   PetscFunctionReturn(0);
80b117cd09SVijay Mahadevan }
81b117cd09SVijay Mahadevan 
82b117cd09SVijay Mahadevan #undef __FUNCT__
83b117cd09SVijay Mahadevan #define __FUNCT__ "DMRefineHierarchy_Moab"
84b117cd09SVijay Mahadevan /*@
85e882eb38SVijay Mahadevan   DMRefineHierarchy_Moab - Generate a multi-level DM hierarchy
86e882eb38SVijay Mahadevan   by succesively refining a coarse mesh.
87b117cd09SVijay Mahadevan 
88b117cd09SVijay Mahadevan   Collective on MPI_Comm
89b117cd09SVijay Mahadevan 
90b117cd09SVijay Mahadevan   Input Parameter:
91e882eb38SVijay Mahadevan + dm  - The DMMoab object
92b117cd09SVijay Mahadevan 
93b117cd09SVijay Mahadevan   Output Parameter:
94e882eb38SVijay Mahadevan + nlevels   - The number of levels of refinement needed to generate the hierarchy
95e882eb38SVijay Mahadevan . dmf  - The DM objects after successive refinement of the hierarchy
96b117cd09SVijay Mahadevan 
97b117cd09SVijay Mahadevan   Level: beginner
98b117cd09SVijay Mahadevan 
99e882eb38SVijay Mahadevan .keywords: DMMoab, generate, refinement
100b117cd09SVijay Mahadevan @*/
101304006b3SVijay Mahadevan PETSC_EXTERN PetscErrorCode  DMRefineHierarchy_Moab(DM dm, PetscInt nlevels, DM dmf[])
102b117cd09SVijay Mahadevan {
103b117cd09SVijay Mahadevan   PetscErrorCode  ierr;
104b117cd09SVijay Mahadevan   PetscInt        i;
105b117cd09SVijay Mahadevan 
106b117cd09SVijay Mahadevan   PetscFunctionBegin;
107b117cd09SVijay Mahadevan 
108e882eb38SVijay Mahadevan   ierr = DMRefine(dm, PetscObjectComm((PetscObject)dm), &dmf[0]);CHKERRQ(ierr);
109e882eb38SVijay Mahadevan   for (i = 1; i < nlevels; i++) {
110e882eb38SVijay Mahadevan     ierr = DMRefine(dmf[i - 1], PetscObjectComm((PetscObject)dm), &dmf[i]);CHKERRQ(ierr);
111b117cd09SVijay Mahadevan   }
112b117cd09SVijay Mahadevan   PetscFunctionReturn(0);
113b117cd09SVijay Mahadevan }
114b117cd09SVijay Mahadevan 
115b117cd09SVijay Mahadevan #undef __FUNCT__
116b117cd09SVijay Mahadevan #define __FUNCT__ "DMCoarsenHierarchy_Moab"
117b117cd09SVijay Mahadevan /*@
118e882eb38SVijay Mahadevan   DMCoarsenHierarchy_Moab - Generate a multi-level DM hierarchy
119e882eb38SVijay Mahadevan   by succesively coarsening a refined mesh.
120b117cd09SVijay Mahadevan 
121b117cd09SVijay Mahadevan   Collective on MPI_Comm
122b117cd09SVijay Mahadevan 
123b117cd09SVijay Mahadevan   Input Parameter:
124e882eb38SVijay Mahadevan + dm  - The DMMoab object
125b117cd09SVijay Mahadevan 
126b117cd09SVijay Mahadevan   Output Parameter:
127e882eb38SVijay Mahadevan + nlevels   - The number of levels of refinement needed to generate the hierarchy
128e882eb38SVijay Mahadevan . dmc  - The DM objects after successive coarsening of the hierarchy
129b117cd09SVijay Mahadevan 
130b117cd09SVijay Mahadevan   Level: beginner
131b117cd09SVijay Mahadevan 
132e882eb38SVijay Mahadevan .keywords: DMMoab, generate, coarsening
133b117cd09SVijay Mahadevan @*/
134304006b3SVijay Mahadevan PETSC_EXTERN PetscErrorCode DMCoarsenHierarchy_Moab(DM dm, PetscInt nlevels, DM dmc[])
135b117cd09SVijay Mahadevan {
136b117cd09SVijay Mahadevan   PetscErrorCode  ierr;
137b117cd09SVijay Mahadevan   PetscInt        i;
138b117cd09SVijay Mahadevan 
139b117cd09SVijay Mahadevan   PetscFunctionBegin;
140b117cd09SVijay Mahadevan 
141e882eb38SVijay Mahadevan   ierr = DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &dmc[0]);CHKERRQ(ierr);
142e882eb38SVijay Mahadevan   for (i = 1; i < nlevels; i++) {
143e882eb38SVijay Mahadevan     ierr = DMCoarsen(dmc[i - 1], PetscObjectComm((PetscObject)dm), &dmc[i]);CHKERRQ(ierr);
144b117cd09SVijay Mahadevan   }
145b117cd09SVijay Mahadevan   PetscFunctionReturn(0);
146b117cd09SVijay Mahadevan }
147b117cd09SVijay Mahadevan 
148*2417220eSVijay Mahadevan PETSC_EXTERN PetscErrorCode DMMoab_Compute_NNZ_From_Connectivity(DM, PetscInt*, PetscInt*, PetscInt*, PetscInt*, PetscBool);
149b117cd09SVijay Mahadevan 
150b117cd09SVijay Mahadevan #undef __FUNCT__
151b117cd09SVijay Mahadevan #define __FUNCT__ "DMCreateInterpolation_Moab"
152b117cd09SVijay Mahadevan /*@
153e882eb38SVijay Mahadevan   DMCreateInterpolation_Moab - Generate the interpolation operators to transform
154e882eb38SVijay Mahadevan   operators (matrices, vectors) from parent level to child level as defined by
155e882eb38SVijay Mahadevan   the DM inputs provided by the user.
156b117cd09SVijay Mahadevan 
157b117cd09SVijay Mahadevan   Collective on MPI_Comm
158b117cd09SVijay Mahadevan 
159b117cd09SVijay Mahadevan   Input Parameter:
160e882eb38SVijay Mahadevan + dm1  - The DMMoab object
161e882eb38SVijay Mahadevan - dm2  - the second, finer DMMoab object
162b117cd09SVijay Mahadevan 
163b117cd09SVijay Mahadevan   Output Parameter:
164e882eb38SVijay Mahadevan + interpl  - The interpolation operator for transferring data between the levels
165e882eb38SVijay Mahadevan - vec      - The scaling vector (optional)
166b117cd09SVijay Mahadevan 
167e882eb38SVijay Mahadevan   Level: developer
168b117cd09SVijay Mahadevan 
169b117cd09SVijay Mahadevan .keywords: DMMoab, create, refinement
170b117cd09SVijay Mahadevan @*/
171304006b3SVijay Mahadevan PETSC_EXTERN PetscErrorCode DMCreateInterpolation_Moab(DM dmp, DM dmc, Mat* interpl, Vec* vec)
172b117cd09SVijay Mahadevan {
173755f3dfbSVijay Mahadevan   DM_Moab         *dmbp, *dmbc;
174b117cd09SVijay Mahadevan   PetscErrorCode   ierr;
175b117cd09SVijay Mahadevan   moab::ErrorCode  merr;
176e882eb38SVijay Mahadevan   PetscInt         dim;
1773f1c6e43SVijay Mahadevan   PetscReal        factor;
178ce27a4eeSVijay Mahadevan   PetscInt         innz, *nnz, ionz, *onz;
179755f3dfbSVijay Mahadevan   PetscInt         nlsizp, nlsizc, nlghsizp, ngsizp, ngsizc;
180a86ed394SVijay Mahadevan   const PetscBool  use_consistent_bases=PETSC_TRUE;
181b117cd09SVijay Mahadevan 
182b117cd09SVijay Mahadevan   PetscFunctionBegin;
183755f3dfbSVijay Mahadevan   PetscValidHeaderSpecific(dmp, DM_CLASSID, 1);
184755f3dfbSVijay Mahadevan   PetscValidHeaderSpecific(dmc, DM_CLASSID, 2);
185755f3dfbSVijay Mahadevan   dmbp = (DM_Moab*)(dmp)->data;
186755f3dfbSVijay Mahadevan   dmbc = (DM_Moab*)(dmc)->data;
187755f3dfbSVijay Mahadevan   nlsizp = dmbp->nloc;// *dmb1->numFields;
188755f3dfbSVijay Mahadevan   nlsizc = dmbc->nloc;// *dmb2->numFields;
189755f3dfbSVijay Mahadevan   ngsizp = dmbp->n; // *dmb1->numFields;
190755f3dfbSVijay Mahadevan   ngsizc = dmbc->n; // *dmb2->numFields;
191755f3dfbSVijay Mahadevan   nlghsizp = (dmbp->nloc + dmbp->nghost); // *dmb1->numFields;
192b117cd09SVijay Mahadevan 
193*2417220eSVijay Mahadevan   // Columns = Parent DoFs ;  Rows = Child DoFs
194755f3dfbSVijay Mahadevan   // Interpolation matrix: \sum_{i=1}^P Owned(Child) * (Owned(Parent) + Ghosted(Parent))
195755f3dfbSVijay Mahadevan   // Size: nlsizc * nlghsizp
196755f3dfbSVijay Mahadevan   PetscInfo4(NULL, "Creating interpolation matrix %D X %D to apply transformation between levels %D -> %D.\n", ngsizc, nlghsizp, dmbp->hlevel, dmbc->hlevel);
197b117cd09SVijay Mahadevan 
198a86ed394SVijay Mahadevan   ierr = DMGetDimension(dmp, &dim);CHKERRQ(ierr);
199a86ed394SVijay Mahadevan 
200941e0cffSVijay Mahadevan   /* allocate the nnz, onz arrays based on block size and local nodes */
201755f3dfbSVijay Mahadevan   ierr = PetscCalloc2(nlsizc, &nnz, nlsizc, &onz);CHKERRQ(ierr);
202941e0cffSVijay Mahadevan 
203941e0cffSVijay Mahadevan   /* Loop through the local elements and compute the relation between the current parent and the refined_level. */
204*2417220eSVijay Mahadevan   for (moab::Range::iterator iter = dmbc->vowned->begin(); iter != dmbc->vowned->end(); iter++) {
205941e0cffSVijay Mahadevan 
206*2417220eSVijay Mahadevan     const moab::EntityHandle vhandle = *iter;
207*2417220eSVijay Mahadevan     /* define local variables */
208*2417220eSVijay Mahadevan     moab::EntityHandle parent;
209*2417220eSVijay Mahadevan     std::vector<moab::EntityHandle> adjs;
210*2417220eSVijay Mahadevan     moab::Range     found;
211*2417220eSVijay Mahadevan 
212*2417220eSVijay Mahadevan     /* store the vertex DoF number */
213*2417220eSVijay Mahadevan     const int ldof = dmbc->lidmap[vhandle - dmbc->seqstart];
214*2417220eSVijay Mahadevan 
215*2417220eSVijay Mahadevan     /* Get adjacency information for current vertex - i.e., all elements of dimension (dim) that connects
216*2417220eSVijay Mahadevan        to the current vertex. We can then decipher if a vertex is ghosted or not and compute the
217*2417220eSVijay Mahadevan        non-zero pattern accordingly. */
218*2417220eSVijay Mahadevan     merr = dmbc->hierarchy->get_adjacencies(vhandle, dmbc->dim, adjs);MBERRNM(merr);
219*2417220eSVijay Mahadevan 
220*2417220eSVijay Mahadevan     /* loop over vertices and update the number of connectivity */
221*2417220eSVijay Mahadevan     for (unsigned jter = 0; jter < adjs.size(); jter++) {
222*2417220eSVijay Mahadevan 
223*2417220eSVijay Mahadevan       const moab::EntityHandle jhandle = adjs[jter];
224941e0cffSVijay Mahadevan 
225941e0cffSVijay Mahadevan       /* Get the relation between the current (coarse) parent and its corresponding (finer) children elements */
226*2417220eSVijay Mahadevan       merr = dmbc->hierarchy->child_to_parent(jhandle, dmbc->hlevel, dmbp->hlevel, &parent);MBERRNM(merr);
227941e0cffSVijay Mahadevan 
228*2417220eSVijay Mahadevan       /* Get connectivity information in canonical ordering for the local element */
229*2417220eSVijay Mahadevan       std::vector<moab::EntityHandle> connp;
230*2417220eSVijay Mahadevan       merr = dmbp->hierarchy->get_connectivity(parent, dmbp->hlevel, connp);MBERRNM(merr);
231a86ed394SVijay Mahadevan 
232*2417220eSVijay Mahadevan       for (unsigned ic=0; ic < connp.size(); ++ic) {
233*2417220eSVijay Mahadevan 
234*2417220eSVijay Mahadevan         /* loop over each element connected to the adjacent vertex and update as needed */
235*2417220eSVijay Mahadevan         /* find the truly user-expected layer of ghosted entities to decipher NNZ pattern */
236*2417220eSVijay Mahadevan         if (found.find(connp[ic]) != found.end()) continue; /* make sure we don't double count shared vertices */
237*2417220eSVijay Mahadevan         if (dmbp->vghost->find(connp[ic]) != dmbp->vghost->end()) onz[ldof]++; /* update out-of-proc onz */
238*2417220eSVijay Mahadevan         else nnz[ldof]++; /* else local vertex */
239*2417220eSVijay Mahadevan         found.insert(connp[ic]);
240*2417220eSVijay Mahadevan       }
241*2417220eSVijay Mahadevan     }
242941e0cffSVijay Mahadevan   }
243941e0cffSVijay Mahadevan 
244*2417220eSVijay Mahadevan   for (int i = 0; i < nlsizc; i++)
245*2417220eSVijay Mahadevan     nnz[i] += 1; /* self count the node */
246941e0cffSVijay Mahadevan 
247941e0cffSVijay Mahadevan   ionz = onz[0];
248941e0cffSVijay Mahadevan   innz = nnz[0];
249755f3dfbSVijay Mahadevan   for (int tc = 0; tc < nlsizc; tc++) {
250941e0cffSVijay Mahadevan     // check for maximum allowed sparsity = fully dense
251755f3dfbSVijay Mahadevan     nnz[tc] = std::min(nlsizp, nnz[tc]);
252*2417220eSVijay Mahadevan     onz[tc] = std::min(ngsizp - nlsizp, onz[tc]);
253*2417220eSVijay Mahadevan 
254*2417220eSVijay Mahadevan     PetscInfo3(NULL, "  %d: NNZ = %d, ONZ = %d\n", tc, nnz[tc], onz[tc]);
255941e0cffSVijay Mahadevan 
256941e0cffSVijay Mahadevan     innz = (innz < nnz[tc] ? nnz[tc] : innz);
257941e0cffSVijay Mahadevan     ionz = (ionz < onz[tc] ? onz[tc] : ionz);
258941e0cffSVijay Mahadevan   }
25964e1c140SVijay Mahadevan 
26064e1c140SVijay Mahadevan   /* create interpolation matrix */
261755f3dfbSVijay Mahadevan   ierr = MatCreate(PetscObjectComm((PetscObject)dmc), interpl);CHKERRQ(ierr);
262755f3dfbSVijay Mahadevan   ierr = MatSetSizes(*interpl, nlsizc, nlsizp, ngsizc, ngsizp);CHKERRQ(ierr);
26364e1c140SVijay Mahadevan   ierr = MatSetType(*interpl, MATAIJ);CHKERRQ(ierr);
26464e1c140SVijay Mahadevan   ierr = MatSetFromOptions(*interpl);CHKERRQ(ierr);
26564e1c140SVijay Mahadevan 
266941e0cffSVijay Mahadevan   ierr = MatSeqAIJSetPreallocation(*interpl, innz, nnz);CHKERRQ(ierr);
267941e0cffSVijay Mahadevan   ierr = MatMPIAIJSetPreallocation(*interpl, innz, nnz, ionz, onz);CHKERRQ(ierr);
268941e0cffSVijay Mahadevan 
269941e0cffSVijay Mahadevan   /* clean up temporary memory */
270941e0cffSVijay Mahadevan   ierr = PetscFree2(nnz, onz);CHKERRQ(ierr);
271b117cd09SVijay Mahadevan 
272b117cd09SVijay Mahadevan   /* set up internal matrix data-structures */
273b117cd09SVijay Mahadevan   ierr = MatSetUp(*interpl);CHKERRQ(ierr);
274b117cd09SVijay Mahadevan 
275a86ed394SVijay Mahadevan   /* Define variables for assembly */
276a86ed394SVijay Mahadevan   std::vector<moab::EntityHandle> children;
277a86ed394SVijay Mahadevan   std::vector<moab::EntityHandle> connp, connc;
278a86ed394SVijay Mahadevan   std::vector<PetscReal> pcoords, ccoords, values_phi;
279a86ed394SVijay Mahadevan 
280a86ed394SVijay Mahadevan   if (use_consistent_bases) {
281*2417220eSVijay Mahadevan     const moab::EntityHandle ehandle = dmbp->elocal->front();
282a86ed394SVijay Mahadevan 
283a86ed394SVijay Mahadevan     merr = dmbp->hierarchy->parent_to_child(ehandle, dmbp->hlevel, dmbc->hlevel, children);MBERRNM(merr);
284a86ed394SVijay Mahadevan 
285a86ed394SVijay Mahadevan     /* Get connectivity and coordinates of the parent vertices */
286a86ed394SVijay Mahadevan     merr = dmbp->hierarchy->get_connectivity(ehandle, dmbp->hlevel, connp);MBERRNM(merr);
287*2417220eSVijay Mahadevan     merr = dmbc->mbiface->get_connectivity(&children[0], children.size(), connc);MBERRNM(merr);
288a86ed394SVijay Mahadevan 
289a86ed394SVijay Mahadevan     std::vector<PetscReal> natparam(3*connc.size(), 0.0);
290a86ed394SVijay Mahadevan     pcoords.resize(connp.size() * 3);
291a86ed394SVijay Mahadevan     ccoords.resize(connc.size() * 3);
292a86ed394SVijay Mahadevan     values_phi.resize(connp.size()*connc.size());
293a86ed394SVijay Mahadevan     /* Get coordinates for connectivity entities in canonical order for both coarse and finer levels */
294a86ed394SVijay Mahadevan     merr = dmbp->hierarchy->get_coordinates(&connp[0], connp.size(), dmbp->hlevel, &pcoords[0]);MBERRNM(merr);
295a86ed394SVijay Mahadevan     merr = dmbc->hierarchy->get_coordinates(&connc[0], connc.size(), dmbc->hlevel, &ccoords[0]);MBERRNM(merr);
296a86ed394SVijay Mahadevan 
297a86ed394SVijay Mahadevan     /* Set values: For each DOF in coarse grid cell, set the contribution or PHI evaluated at each fine grid DOF point */
298a86ed394SVijay Mahadevan     for (unsigned tc = 0; tc < connc.size(); tc++) {
299a86ed394SVijay Mahadevan       const PetscInt offset = tc * 3;
300a86ed394SVijay Mahadevan 
301a86ed394SVijay Mahadevan       /* Scale ccoords relative to pcoords */
302a86ed394SVijay Mahadevan       ierr = DMMoabPToRMapping(dim, connp.size(), &pcoords[0], &ccoords[offset], &natparam[offset], &values_phi[connp.size()*tc]);CHKERRQ(ierr);
303a86ed394SVijay Mahadevan     }
304a86ed394SVijay Mahadevan   }
305a86ed394SVijay Mahadevan   else {
306a86ed394SVijay Mahadevan     factor = std::pow(2.0 /*degree_P_for_refinement*/, (dmbc->hlevel - dmbp->hlevel) * dmbp->dim * 1.0);
307a86ed394SVijay Mahadevan   }
308a86ed394SVijay Mahadevan 
309755f3dfbSVijay Mahadevan   /* TODO: Decipher the correct non-zero pattern. There is still some issue with onz allocation */
310*2417220eSVijay Mahadevan   ierr = MatSetOption(*interpl, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);CHKERRQ(ierr);
311b117cd09SVijay Mahadevan 
312e882eb38SVijay Mahadevan   /* Loop through the remaining vertices. These vertices appear only on the current refined_level. */
313*2417220eSVijay Mahadevan   for (moab::Range::iterator iter = dmbp->elocal->begin(); iter != dmbp->elocal->end(); iter++) {
314b117cd09SVijay Mahadevan 
315b117cd09SVijay Mahadevan     const moab::EntityHandle ehandle = *iter;
316b117cd09SVijay Mahadevan 
317b117cd09SVijay Mahadevan     /* Get the relation between the current (coarse) parent and its corresponding (finer) children elements */
318a86ed394SVijay Mahadevan     children.clear();
319a86ed394SVijay Mahadevan     connc.clear();
320755f3dfbSVijay Mahadevan     merr = dmbp->hierarchy->parent_to_child(ehandle, dmbp->hlevel, dmbc->hlevel, children);MBERRNM(merr);
321b117cd09SVijay Mahadevan 
322b117cd09SVijay Mahadevan     /* Get connectivity and coordinates of the parent vertices */
323755f3dfbSVijay Mahadevan     merr = dmbp->hierarchy->get_connectivity(ehandle, dmbp->hlevel, connp);MBERRNM(merr);
324*2417220eSVijay Mahadevan     merr = dmbc->mbiface->get_connectivity(&children[0], children.size(), connc);MBERRNM(merr);
325b117cd09SVijay Mahadevan 
326a86ed394SVijay Mahadevan     pcoords.resize(connp.size() * 3);
327a86ed394SVijay Mahadevan     ccoords.resize(connc.size() * 3);
328b117cd09SVijay Mahadevan     /* Get coordinates for connectivity entities in canonical order for both coarse and finer levels */
329755f3dfbSVijay Mahadevan     merr = dmbp->hierarchy->get_coordinates(&connp[0], connp.size(), dmbp->hlevel, &pcoords[0]);MBERRNM(merr);
330755f3dfbSVijay Mahadevan     merr = dmbc->hierarchy->get_coordinates(&connc[0], connc.size(), dmbc->hlevel, &ccoords[0]);MBERRNM(merr);
331b117cd09SVijay Mahadevan 
332b117cd09SVijay Mahadevan     std::vector<int> dofsp(connp.size()), dofsc(connc.size());
333b117cd09SVijay Mahadevan     /* TODO: specific to scalar system - use GetDofs */
334755f3dfbSVijay Mahadevan     ierr = DMMoabGetDofsBlocked(dmp, connp.size(), &connp[0], &dofsp[0]);CHKERRQ(ierr);
335755f3dfbSVijay Mahadevan     ierr = DMMoabGetDofsBlocked(dmc, connc.size(), &connc[0], &dofsc[0]);CHKERRQ(ierr);
336b117cd09SVijay Mahadevan 
337a86ed394SVijay Mahadevan     /* Compute the actual interpolation weights when projecting solution/residual between levels */
338a86ed394SVijay Mahadevan     if (use_consistent_bases) {
339a86ed394SVijay Mahadevan 
340a86ed394SVijay Mahadevan       /* Use the cached values of natural parameteric coordinates and basis pre-evaluated.
341a86ed394SVijay Mahadevan          We are making an assumption here that UMR used in GMG to generate the hierarchy uses
342a86ed394SVijay Mahadevan          the same template for all elements; This will fail for mixed element meshes (TRI/QUAD).
343a86ed394SVijay Mahadevan 
344*2417220eSVijay Mahadevan          TODO: Fix the above assumption by caching data for families (especially for Tets and mixed meshes)
345a86ed394SVijay Mahadevan       */
346a86ed394SVijay Mahadevan 
347a86ed394SVijay Mahadevan       /* Set values: For each DOF in coarse grid cell, set the contribution or PHI evaluated at each fine grid DOF point */
348a86ed394SVijay Mahadevan       for (unsigned tc = 0; tc < connc.size(); tc++) {
349a86ed394SVijay Mahadevan         /* TODO: Check if we should be using INSERT_VALUES instead */
350a86ed394SVijay Mahadevan         ierr = MatSetValues(*interpl, 1, &dofsc[tc], connp.size(), &dofsp[0], &values_phi[connp.size()*tc], ADD_VALUES);CHKERRQ(ierr);
351a86ed394SVijay Mahadevan       }
352a86ed394SVijay Mahadevan     }
353a86ed394SVijay Mahadevan     else {
354e882eb38SVijay Mahadevan       /* Compute the interpolation weights by determining distance of 1-ring
355755f3dfbSVijay Mahadevan          neighbor vertices from current vertex
356755f3dfbSVijay Mahadevan 
357a86ed394SVijay Mahadevan          This should be used only when FEM basis is not used for the discretization.
358a86ed394SVijay Mahadevan          Else, the consistent interface to compute the basis function for interpolation
359a86ed394SVijay Mahadevan          between the levels should be evaluated correctly to preserve convergence of GMG.
360*2417220eSVijay Mahadevan          Shephard's basis will be terrible for any unsmooth problems.
361755f3dfbSVijay Mahadevan       */
362755f3dfbSVijay Mahadevan       values_phi.resize(connp.size());
363755f3dfbSVijay Mahadevan       for (unsigned tc = 0; tc < connc.size(); tc++) {
364755f3dfbSVijay Mahadevan 
365a86ed394SVijay Mahadevan         PetscReal normsum = 0.0;
366755f3dfbSVijay Mahadevan         for (unsigned tp = 0; tp < connp.size(); tp++) {
367755f3dfbSVijay Mahadevan           values_phi[tp] = 0.0;
368e882eb38SVijay Mahadevan           for (unsigned k = 0; k < 3; k++)
369755f3dfbSVijay Mahadevan             values_phi[tp] += std::pow(pcoords[tp * 3 + k] - ccoords[k + tc * 3], dim);
370755f3dfbSVijay Mahadevan           if (values_phi[tp] < 1e-12) {
371755f3dfbSVijay Mahadevan             values_phi[tp] = 1e12;
372b117cd09SVijay Mahadevan           }
373b117cd09SVijay Mahadevan           else {
374755f3dfbSVijay Mahadevan             //values_phi[tp] = std::pow(values_phi[tp], -1.0/dim);
375755f3dfbSVijay Mahadevan             values_phi[tp] = std::pow(values_phi[tp], -1.0);
376755f3dfbSVijay Mahadevan             normsum += values_phi[tp];
377b117cd09SVijay Mahadevan           }
378b117cd09SVijay Mahadevan         }
379755f3dfbSVijay Mahadevan         for (unsigned tp = 0; tp < connp.size(); tp++) {
380755f3dfbSVijay Mahadevan           if (values_phi[tp] > 1e11)
381755f3dfbSVijay Mahadevan             values_phi[tp] = factor * 0.5 / connp.size();
382b117cd09SVijay Mahadevan           else
383755f3dfbSVijay Mahadevan             values_phi[tp] = factor * values_phi[tp] * 0.5 / (connp.size() * normsum);
384b117cd09SVijay Mahadevan         }
385755f3dfbSVijay Mahadevan         ierr = MatSetValues(*interpl, 1, &dofsc[tc], connp.size(), &dofsp[0], &values_phi[0], ADD_VALUES);CHKERRQ(ierr);
386b117cd09SVijay Mahadevan       }
387a86ed394SVijay Mahadevan     }
388b117cd09SVijay Mahadevan   }
389304006b3SVijay Mahadevan   if (vec) *vec = NULL;
390b117cd09SVijay Mahadevan   ierr = MatAssemblyBegin(*interpl, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
391b117cd09SVijay Mahadevan   ierr = MatAssemblyEnd(*interpl, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
392b117cd09SVijay Mahadevan   PetscFunctionReturn(0);
393b117cd09SVijay Mahadevan }
394b117cd09SVijay Mahadevan 
395b117cd09SVijay Mahadevan #undef __FUNCT__
396b117cd09SVijay Mahadevan #define __FUNCT__ "DMCreateInjection_Moab"
397b117cd09SVijay Mahadevan /*@
398b117cd09SVijay Mahadevan   DMCreateInjection_Moab - Generate a multi-level uniform refinement hierarchy
399b117cd09SVijay Mahadevan   by succesively refining a coarse mesh, already defined in the DM object
400b117cd09SVijay Mahadevan   provided by the user.
401b117cd09SVijay Mahadevan 
402b117cd09SVijay Mahadevan   Collective on MPI_Comm
403b117cd09SVijay Mahadevan 
404b117cd09SVijay Mahadevan   Input Parameter:
405b117cd09SVijay Mahadevan . dmb  - The DMMoab object
406b117cd09SVijay Mahadevan 
407b117cd09SVijay Mahadevan   Output Parameter:
408b117cd09SVijay Mahadevan . nlevels   - The number of levels of refinement needed to generate the hierarchy
409b117cd09SVijay Mahadevan + ldegrees  - The degree of refinement at each level in the hierarchy
410b117cd09SVijay Mahadevan 
411b117cd09SVijay Mahadevan   Level: beginner
412b117cd09SVijay Mahadevan 
413b117cd09SVijay Mahadevan .keywords: DMMoab, create, refinement
414b117cd09SVijay Mahadevan @*/
415304006b3SVijay Mahadevan PETSC_EXTERN PetscErrorCode DMCreateInjection_Moab(DM dm1, DM dm2, VecScatter* ctx)
416b117cd09SVijay Mahadevan {
417e882eb38SVijay Mahadevan   //DM_Moab        *dmmoab;
418b117cd09SVijay Mahadevan 
419b117cd09SVijay Mahadevan   PetscFunctionBegin;
420b117cd09SVijay Mahadevan   PetscValidHeaderSpecific(dm1, DM_CLASSID, 1);
421b117cd09SVijay Mahadevan   PetscValidHeaderSpecific(dm2, DM_CLASSID, 2);
422e882eb38SVijay Mahadevan   //dmmoab = (DM_Moab*)(dm1)->data;
423b117cd09SVijay Mahadevan 
424b117cd09SVijay Mahadevan   PetscPrintf(PETSC_COMM_WORLD, "[DMCreateInjection_Moab] :: Placeholder\n");
425b117cd09SVijay Mahadevan   PetscFunctionReturn(0);
426b117cd09SVijay Mahadevan }
427b117cd09SVijay Mahadevan 
428b117cd09SVijay Mahadevan 
429b117cd09SVijay Mahadevan #undef __FUNCT__
430b117cd09SVijay Mahadevan #define __FUNCT__ "DM_UMR_Moab_Private"
431b117cd09SVijay Mahadevan PetscErrorCode  DM_UMR_Moab_Private(DM dm, MPI_Comm comm, PetscBool refine, DM *dmref)
432b117cd09SVijay Mahadevan {
433b117cd09SVijay Mahadevan   PetscErrorCode  ierr;
434e882eb38SVijay Mahadevan   PetscInt        i, dim;
435b117cd09SVijay Mahadevan   DM              dm2;
436b117cd09SVijay Mahadevan   moab::ErrorCode merr;
437b117cd09SVijay Mahadevan   DM_Moab        *dmb = (DM_Moab*)dm->data, *dd2;
438b117cd09SVijay Mahadevan 
439b117cd09SVijay Mahadevan   PetscFunctionBegin;
440b117cd09SVijay Mahadevan   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
441b117cd09SVijay Mahadevan   PetscValidPointer(dmref, 4);
442b117cd09SVijay Mahadevan 
443b117cd09SVijay Mahadevan   if ( (dmb->hlevel == dmb->nhlevels && refine) || (dmb->hlevel == 0 && !refine) ) {
444e882eb38SVijay Mahadevan     if (dmb->hlevel + 1 > dmb->nhlevels && refine) PetscInfo2(NULL, "Invalid multigrid refinement hierarchy level specified (%D). MOAB UMR max levels = %D. Creating a NULL object.\n", dmb->hlevel + 1, dmb->nhlevels);
445e882eb38SVijay Mahadevan     if (dmb->hlevel - 1 < 0 && !refine) PetscInfo1(NULL, "Invalid multigrid coarsen hierarchy level specified (%D). Creating a NULL object.\n", dmb->hlevel - 1);
446e882eb38SVijay Mahadevan     *dmref = PETSC_NULL;
447b117cd09SVijay Mahadevan     PetscFunctionReturn(0);
448b117cd09SVijay Mahadevan   }
449b117cd09SVijay Mahadevan 
450b117cd09SVijay Mahadevan   ierr = DMMoabCreate(PetscObjectComm((PetscObject)dm), &dm2);CHKERRQ(ierr);
451b117cd09SVijay Mahadevan   dd2 = (DM_Moab*)dm2->data;
452b117cd09SVijay Mahadevan 
453b117cd09SVijay Mahadevan   dd2->mbiface = dmb->mbiface;
4549daf19fdSVijay Mahadevan #ifdef MOAB_HAVE_MPI
455b117cd09SVijay Mahadevan   dd2->pcomm = dmb->pcomm;
4569daf19fdSVijay Mahadevan #endif
457b117cd09SVijay Mahadevan   dd2->icreatedinstance = PETSC_FALSE;
45864e1c140SVijay Mahadevan   dd2->nghostrings = dmb->nghostrings;
459b117cd09SVijay Mahadevan 
460b117cd09SVijay Mahadevan   /* set the new level based on refinement/coarsening */
461b117cd09SVijay Mahadevan   if (refine) {
462b117cd09SVijay Mahadevan     dd2->hlevel = dmb->hlevel + 1;
463b117cd09SVijay Mahadevan   }
464b117cd09SVijay Mahadevan   else {
465b117cd09SVijay Mahadevan     dd2->hlevel = dmb->hlevel - 1;
466b117cd09SVijay Mahadevan   }
467b117cd09SVijay Mahadevan 
468b117cd09SVijay Mahadevan   /* Copy the multilevel hierarchy pointers in MOAB */
469b117cd09SVijay Mahadevan   dd2->hierarchy = dmb->hierarchy;
470b117cd09SVijay Mahadevan   dd2->nhlevels = dmb->nhlevels;
471b117cd09SVijay Mahadevan   ierr = PetscMalloc1(dd2->nhlevels + 1, &dd2->hsets);CHKERRQ(ierr);
472b117cd09SVijay Mahadevan   for (i = 0; i <= dd2->nhlevels; i++) {
473b117cd09SVijay Mahadevan     dd2->hsets[i] = dmb->hsets[i];
474b117cd09SVijay Mahadevan   }
475b117cd09SVijay Mahadevan   dd2->fileset = dd2->hsets[dd2->hlevel];
476b117cd09SVijay Mahadevan 
477b117cd09SVijay Mahadevan   /* do the remaining initializations for DMMoab */
478b117cd09SVijay Mahadevan   dd2->bs = dmb->bs;
479b117cd09SVijay Mahadevan   dd2->numFields = dmb->numFields;
480b117cd09SVijay Mahadevan   dd2->rw_dbglevel = dmb->rw_dbglevel;
481b117cd09SVijay Mahadevan   dd2->partition_by_rank = dmb->partition_by_rank;
482b117cd09SVijay Mahadevan   ierr = PetscStrcpy(dd2->extra_read_options, dmb->extra_read_options);CHKERRQ(ierr);
483b117cd09SVijay Mahadevan   ierr = PetscStrcpy(dd2->extra_write_options, dmb->extra_write_options);CHKERRQ(ierr);
484b117cd09SVijay Mahadevan   dd2->read_mode = dmb->read_mode;
485b117cd09SVijay Mahadevan   dd2->write_mode = dmb->write_mode;
486b117cd09SVijay Mahadevan 
487b117cd09SVijay Mahadevan   /* set global ID tag handle */
488b117cd09SVijay Mahadevan   ierr = DMMoabSetLocalToGlobalTag(dm2, dmb->ltog_tag);CHKERRQ(ierr);
489b117cd09SVijay Mahadevan 
490b117cd09SVijay Mahadevan   merr = dd2->mbiface->tag_get_handle(MATERIAL_SET_TAG_NAME, dd2->material_tag);MBERRNM(merr);
491b117cd09SVijay Mahadevan 
492b117cd09SVijay Mahadevan   ierr = DMSetOptionsPrefix(dm2, ((PetscObject)dm)->prefix);CHKERRQ(ierr);
493b117cd09SVijay Mahadevan   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
494b117cd09SVijay Mahadevan   ierr = DMSetDimension(dm2, dim);CHKERRQ(ierr);
495b117cd09SVijay Mahadevan 
496b117cd09SVijay Mahadevan   /* allow overloaded (user replaced) operations to be inherited by refinement clones */
497b117cd09SVijay Mahadevan   dm2->ops->creatematrix = dm->ops->creatematrix;
498b117cd09SVijay Mahadevan 
499b117cd09SVijay Mahadevan   /* copy fill information if given */
500b117cd09SVijay Mahadevan   ierr = DMMoabSetBlockFills(dm2, dmb->dfill, dmb->ofill);CHKERRQ(ierr);
501b117cd09SVijay Mahadevan 
502b117cd09SVijay Mahadevan   /* copy vector type information */
503b117cd09SVijay Mahadevan   ierr = DMSetMatType(dm2, dm->mattype);CHKERRQ(ierr);
504b117cd09SVijay Mahadevan   ierr = DMSetVecType(dm2, dm->vectype);CHKERRQ(ierr);
5053f1c6e43SVijay Mahadevan   dd2->numFields = dmb->numFields;
5063f1c6e43SVijay Mahadevan   if (dmb->numFields) {
507b117cd09SVijay Mahadevan     ierr = DMMoabSetFieldNames(dm2, dmb->numFields, dmb->fieldNames);CHKERRQ(ierr);
5083f1c6e43SVijay Mahadevan   }
509b117cd09SVijay Mahadevan 
510b117cd09SVijay Mahadevan   ierr = DMSetFromOptions(dm2);CHKERRQ(ierr);
511b117cd09SVijay Mahadevan 
512b117cd09SVijay Mahadevan   /* recreate Dof numbering for the refined DM and make sure the distribution is correctly populated */
513b117cd09SVijay Mahadevan   ierr = DMSetUp(dm2);CHKERRQ(ierr);
514b117cd09SVijay Mahadevan 
515b117cd09SVijay Mahadevan   *dmref = dm2;
516b117cd09SVijay Mahadevan   PetscFunctionReturn(0);
517b117cd09SVijay Mahadevan }
518b117cd09SVijay Mahadevan 
519b117cd09SVijay Mahadevan 
520b117cd09SVijay Mahadevan #undef __FUNCT__
521b117cd09SVijay Mahadevan #define __FUNCT__ "DMRefine_Moab"
522b117cd09SVijay Mahadevan /*@
523b117cd09SVijay Mahadevan   DMRefine_Moab - Generate a multi-level uniform refinement hierarchy
524b117cd09SVijay Mahadevan   by succesively refining a coarse mesh, already defined in the DM object
525b117cd09SVijay Mahadevan   provided by the user.
526b117cd09SVijay Mahadevan 
527e882eb38SVijay Mahadevan   Collective on DM
528b117cd09SVijay Mahadevan 
529b117cd09SVijay Mahadevan   Input Parameter:
530e882eb38SVijay Mahadevan + dm  - The DMMoab object
531e882eb38SVijay Mahadevan - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
532b117cd09SVijay Mahadevan 
533b117cd09SVijay Mahadevan   Output Parameter:
534e882eb38SVijay Mahadevan . dmf - the refined DM, or NULL
535b117cd09SVijay Mahadevan 
536e882eb38SVijay Mahadevan   Note: If no refinement was done, the return value is NULL
537e882eb38SVijay Mahadevan 
538e882eb38SVijay Mahadevan   Level: developer
539b117cd09SVijay Mahadevan 
540b117cd09SVijay Mahadevan .keywords: DMMoab, create, refinement
541b117cd09SVijay Mahadevan @*/
542304006b3SVijay Mahadevan PETSC_EXTERN PetscErrorCode DMRefine_Moab(DM dm, MPI_Comm comm, DM* dmf)
543b117cd09SVijay Mahadevan {
544b117cd09SVijay Mahadevan   PetscErrorCode  ierr;
545b117cd09SVijay Mahadevan 
546b117cd09SVijay Mahadevan   PetscFunctionBegin;
547b117cd09SVijay Mahadevan   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
548b117cd09SVijay Mahadevan 
549b117cd09SVijay Mahadevan   ierr = DM_UMR_Moab_Private(dm, comm, PETSC_TRUE, dmf);CHKERRQ(ierr);
550b117cd09SVijay Mahadevan   PetscFunctionReturn(0);
551b117cd09SVijay Mahadevan }
552b117cd09SVijay Mahadevan 
553b117cd09SVijay Mahadevan #undef __FUNCT__
554b117cd09SVijay Mahadevan #define __FUNCT__ "DMCoarsen_Moab"
555b117cd09SVijay Mahadevan /*@
556b117cd09SVijay Mahadevan   DMCoarsen_Moab - Generate a multi-level uniform refinement hierarchy
557b117cd09SVijay Mahadevan   by succesively refining a coarse mesh, already defined in the DM object
558b117cd09SVijay Mahadevan   provided by the user.
559b117cd09SVijay Mahadevan 
560e882eb38SVijay Mahadevan   Collective on DM
561b117cd09SVijay Mahadevan 
562b117cd09SVijay Mahadevan   Input Parameter:
563e882eb38SVijay Mahadevan . dm  - The DMMoab object
564e882eb38SVijay Mahadevan - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
565b117cd09SVijay Mahadevan 
566b117cd09SVijay Mahadevan   Output Parameter:
567e882eb38SVijay Mahadevan . dmf - the coarsened DM, or NULL
568b117cd09SVijay Mahadevan 
569e882eb38SVijay Mahadevan   Note: If no coarsening was done, the return value is NULL
570b117cd09SVijay Mahadevan 
571e882eb38SVijay Mahadevan   Level: developer
572e882eb38SVijay Mahadevan 
573e882eb38SVijay Mahadevan .keywords: DMMoab, create, coarsening
574b117cd09SVijay Mahadevan @*/
575304006b3SVijay Mahadevan PETSC_EXTERN PetscErrorCode DMCoarsen_Moab(DM dm, MPI_Comm comm, DM* dmc)
576b117cd09SVijay Mahadevan {
577b117cd09SVijay Mahadevan   PetscErrorCode  ierr;
578b117cd09SVijay Mahadevan 
579b117cd09SVijay Mahadevan   PetscFunctionBegin;
580b117cd09SVijay Mahadevan   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
581b117cd09SVijay Mahadevan 
582b117cd09SVijay Mahadevan   ierr = DM_UMR_Moab_Private(dm, comm, PETSC_FALSE, dmc);CHKERRQ(ierr);
583b117cd09SVijay Mahadevan   PetscFunctionReturn(0);
584b117cd09SVijay Mahadevan }
585