xref: /petsc/src/dm/interface/dm.c (revision db6843f5416b853f0c7dc8a831291c8a6f8016af)
1 #include <petsc-private/dmimpl.h>     /*I      "petscdm.h"     I*/
2 #include <petscsf.h>
3 #include <petscds.h>
4 
5 PetscClassId  DM_CLASSID;
6 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal;
7 
8 const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DM_BOUNDARY_",0};
9 
10 #undef __FUNCT__
11 #define __FUNCT__ "DMCreate"
12 /*@
13   DMCreate - Creates an empty DM object. The type can then be set with DMSetType().
14 
15    If you never  call DMSetType()  it will generate an
16    error when you try to use the vector.
17 
18   Collective on MPI_Comm
19 
20   Input Parameter:
21 . comm - The communicator for the DM object
22 
23   Output Parameter:
24 . dm - The DM object
25 
26   Level: beginner
27 
28 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE
29 @*/
30 PetscErrorCode  DMCreate(MPI_Comm comm,DM *dm)
31 {
32   DM             v;
33   PetscErrorCode ierr;
34 
35   PetscFunctionBegin;
36   PetscValidPointer(dm,2);
37   *dm = NULL;
38   ierr = PetscSysInitializePackage();CHKERRQ(ierr);
39   ierr = VecInitializePackage();CHKERRQ(ierr);
40   ierr = MatInitializePackage();CHKERRQ(ierr);
41   ierr = DMInitializePackage();CHKERRQ(ierr);
42 
43   ierr = PetscHeaderCreate(v, _p_DM, struct _DMOps, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr);
44   ierr = PetscMemzero(v->ops, sizeof(struct _DMOps));CHKERRQ(ierr);
45 
46 
47   v->ltogmap              = NULL;
48   v->bs                   = 1;
49   v->coloringtype         = IS_COLORING_GLOBAL;
50   ierr                    = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr);
51   ierr                    = PetscSFCreate(comm, &v->defaultSF);CHKERRQ(ierr);
52   v->defaultSection       = NULL;
53   v->defaultGlobalSection = NULL;
54   v->L                    = NULL;
55   v->maxCell              = NULL;
56   {
57     PetscInt i;
58     for (i = 0; i < 10; ++i) {
59       v->nullspaceConstructors[i] = NULL;
60     }
61   }
62   ierr = PetscDSCreate(comm, &v->prob);CHKERRQ(ierr);
63   v->dmBC = NULL;
64   v->outputSequenceNum = -1;
65   v->outputSequenceVal = 0.0;
66   ierr = DMSetVecType(v,VECSTANDARD);CHKERRQ(ierr);
67   ierr = DMSetMatType(v,MATAIJ);CHKERRQ(ierr);
68   *dm = v;
69   PetscFunctionReturn(0);
70 }
71 
72 #undef __FUNCT__
73 #define __FUNCT__ "DMClone"
74 /*@
75   DMClone - Creates a DM object with the same topology as the original.
76 
77   Collective on MPI_Comm
78 
79   Input Parameter:
80 . dm - The original DM object
81 
82   Output Parameter:
83 . newdm  - The new DM object
84 
85   Level: beginner
86 
87 .keywords: DM, topology, create
88 @*/
89 PetscErrorCode DMClone(DM dm, DM *newdm)
90 {
91   PetscSF        sf;
92   Vec            coords;
93   void          *ctx;
94   PetscInt       dim;
95   PetscErrorCode ierr;
96 
97   PetscFunctionBegin;
98   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
99   PetscValidPointer(newdm,2);
100   ierr = DMCreate(PetscObjectComm((PetscObject)dm), newdm);CHKERRQ(ierr);
101   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
102   ierr = DMSetDimension(*newdm, dim);CHKERRQ(ierr);
103   if (dm->ops->clone) {
104     ierr = (*dm->ops->clone)(dm, newdm);CHKERRQ(ierr);
105   }
106   (*newdm)->setupcalled = PETSC_TRUE;
107   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
108   ierr = DMSetPointSF(*newdm, sf);CHKERRQ(ierr);
109   ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr);
110   ierr = DMSetApplicationContext(*newdm, ctx);CHKERRQ(ierr);
111   ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr);
112   if (coords) {
113     ierr = DMSetCoordinatesLocal(*newdm, coords);CHKERRQ(ierr);
114   } else {
115     ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr);
116     if (coords) {ierr = DMSetCoordinates(*newdm, coords);CHKERRQ(ierr);}
117   }
118   if (dm->maxCell) {
119     const PetscReal *maxCell, *L;
120     ierr = DMGetPeriodicity(dm,     &maxCell, &L);CHKERRQ(ierr);
121     ierr = DMSetPeriodicity(*newdm,  maxCell,  L);CHKERRQ(ierr);
122   }
123   PetscFunctionReturn(0);
124 }
125 
126 #undef __FUNCT__
127 #define __FUNCT__ "DMSetVecType"
128 /*@C
129        DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
130 
131    Logically Collective on DMDA
132 
133    Input Parameter:
134 +  da - initial distributed array
135 .  ctype - the vector type, currently either VECSTANDARD or VECCUSP
136 
137    Options Database:
138 .   -dm_vec_type ctype
139 
140    Level: intermediate
141 
142 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType, VecType, DMGetVecType()
143 @*/
144 PetscErrorCode  DMSetVecType(DM da,VecType ctype)
145 {
146   PetscErrorCode ierr;
147 
148   PetscFunctionBegin;
149   PetscValidHeaderSpecific(da,DM_CLASSID,1);
150   ierr = PetscFree(da->vectype);CHKERRQ(ierr);
151   ierr = PetscStrallocpy(ctype,(char**)&da->vectype);CHKERRQ(ierr);
152   PetscFunctionReturn(0);
153 }
154 
155 #undef __FUNCT__
156 #define __FUNCT__ "DMGetVecType"
157 /*@C
158        DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
159 
160    Logically Collective on DMDA
161 
162    Input Parameter:
163 .  da - initial distributed array
164 
165    Output Parameter:
166 .  ctype - the vector type
167 
168    Level: intermediate
169 
170 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType, VecType
171 @*/
172 PetscErrorCode  DMGetVecType(DM da,VecType *ctype)
173 {
174   PetscFunctionBegin;
175   PetscValidHeaderSpecific(da,DM_CLASSID,1);
176   *ctype = da->vectype;
177   PetscFunctionReturn(0);
178 }
179 
180 #undef __FUNCT__
181 #define __FUNCT__ "VecGetDM"
182 /*@
183   VecGetDM - Gets the DM defining the data layout of the vector
184 
185   Not collective
186 
187   Input Parameter:
188 . v - The Vec
189 
190   Output Parameter:
191 . dm - The DM
192 
193   Level: intermediate
194 
195 .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
196 @*/
197 PetscErrorCode VecGetDM(Vec v, DM *dm)
198 {
199   PetscErrorCode ierr;
200 
201   PetscFunctionBegin;
202   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
203   PetscValidPointer(dm,2);
204   ierr = PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr);
205   PetscFunctionReturn(0);
206 }
207 
208 #undef __FUNCT__
209 #define __FUNCT__ "VecSetDM"
210 /*@
211   VecSetDM - Sets the DM defining the data layout of the vector
212 
213   Not collective
214 
215   Input Parameters:
216 + v - The Vec
217 - dm - The DM
218 
219   Level: intermediate
220 
221 .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
222 @*/
223 PetscErrorCode VecSetDM(Vec v, DM dm)
224 {
225   PetscErrorCode ierr;
226 
227   PetscFunctionBegin;
228   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
229   if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2);
230   ierr = PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr);
231   PetscFunctionReturn(0);
232 }
233 
234 #undef __FUNCT__
235 #define __FUNCT__ "DMSetMatType"
236 /*@C
237        DMSetMatType - Sets the type of matrix created with DMCreateMatrix()
238 
239    Logically Collective on DM
240 
241    Input Parameter:
242 +  dm - the DM context
243 .  ctype - the matrix type
244 
245    Options Database:
246 .   -dm_mat_type ctype
247 
248    Level: intermediate
249 
250 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType()
251 @*/
252 PetscErrorCode  DMSetMatType(DM dm,MatType ctype)
253 {
254   PetscErrorCode ierr;
255 
256   PetscFunctionBegin;
257   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
258   ierr = PetscFree(dm->mattype);CHKERRQ(ierr);
259   ierr = PetscStrallocpy(ctype,(char**)&dm->mattype);CHKERRQ(ierr);
260   PetscFunctionReturn(0);
261 }
262 
263 #undef __FUNCT__
264 #define __FUNCT__ "DMGetMatType"
265 /*@C
266        DMGetMatType - Gets the type of matrix created with DMCreateMatrix()
267 
268    Logically Collective on DM
269 
270    Input Parameter:
271 .  dm - the DM context
272 
273    Output Parameter:
274 .  ctype - the matrix type
275 
276    Options Database:
277 .   -dm_mat_type ctype
278 
279    Level: intermediate
280 
281 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType()
282 @*/
283 PetscErrorCode  DMGetMatType(DM dm,MatType *ctype)
284 {
285   PetscFunctionBegin;
286   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
287   *ctype = dm->mattype;
288   PetscFunctionReturn(0);
289 }
290 
291 #undef __FUNCT__
292 #define __FUNCT__ "MatGetDM"
293 /*@
294   MatGetDM - Gets the DM defining the data layout of the matrix
295 
296   Not collective
297 
298   Input Parameter:
299 . A - The Mat
300 
301   Output Parameter:
302 . dm - The DM
303 
304   Level: intermediate
305 
306 .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType()
307 @*/
308 PetscErrorCode MatGetDM(Mat A, DM *dm)
309 {
310   PetscErrorCode ierr;
311 
312   PetscFunctionBegin;
313   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
314   PetscValidPointer(dm,2);
315   ierr = PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr);
316   PetscFunctionReturn(0);
317 }
318 
319 #undef __FUNCT__
320 #define __FUNCT__ "MatSetDM"
321 /*@
322   MatSetDM - Sets the DM defining the data layout of the matrix
323 
324   Not collective
325 
326   Input Parameters:
327 + A - The Mat
328 - dm - The DM
329 
330   Level: intermediate
331 
332 .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType()
333 @*/
334 PetscErrorCode MatSetDM(Mat A, DM dm)
335 {
336   PetscErrorCode ierr;
337 
338   PetscFunctionBegin;
339   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
340   if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2);
341   ierr = PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr);
342   PetscFunctionReturn(0);
343 }
344 
345 #undef __FUNCT__
346 #define __FUNCT__ "DMSetOptionsPrefix"
347 /*@C
348    DMSetOptionsPrefix - Sets the prefix used for searching for all
349    DMDA options in the database.
350 
351    Logically Collective on DMDA
352 
353    Input Parameter:
354 +  da - the DMDA context
355 -  prefix - the prefix to prepend to all option names
356 
357    Notes:
358    A hyphen (-) must NOT be given at the beginning of the prefix name.
359    The first character of all runtime options is AUTOMATICALLY the hyphen.
360 
361    Level: advanced
362 
363 .keywords: DMDA, set, options, prefix, database
364 
365 .seealso: DMSetFromOptions()
366 @*/
367 PetscErrorCode  DMSetOptionsPrefix(DM dm,const char prefix[])
368 {
369   PetscErrorCode ierr;
370 
371   PetscFunctionBegin;
372   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
373   ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr);
374   PetscFunctionReturn(0);
375 }
376 
377 #undef __FUNCT__
378 #define __FUNCT__ "DMDestroy"
379 /*@
380     DMDestroy - Destroys a vector packer or DMDA.
381 
382     Collective on DM
383 
384     Input Parameter:
385 .   dm - the DM object to destroy
386 
387     Level: developer
388 
389 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
390 
391 @*/
392 PetscErrorCode  DMDestroy(DM *dm)
393 {
394   PetscInt       i, cnt = 0;
395   DMNamedVecLink nlink,nnext;
396   PetscErrorCode ierr;
397 
398   PetscFunctionBegin;
399   if (!*dm) PetscFunctionReturn(0);
400   PetscValidHeaderSpecific((*dm),DM_CLASSID,1);
401 
402   /* count all the circular references of DM and its contained Vecs */
403   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
404     if ((*dm)->localin[i])  cnt++;
405     if ((*dm)->globalin[i]) cnt++;
406   }
407   for (nlink=(*dm)->namedglobal; nlink; nlink=nlink->next) cnt++;
408   for (nlink=(*dm)->namedlocal; nlink; nlink=nlink->next) cnt++;
409   if ((*dm)->x) {
410     DM obj;
411     ierr = VecGetDM((*dm)->x, &obj);CHKERRQ(ierr);
412     if (obj == *dm) cnt++;
413   }
414 
415   if (--((PetscObject)(*dm))->refct - cnt > 0) {*dm = 0; PetscFunctionReturn(0);}
416   /*
417      Need this test because the dm references the vectors that
418      reference the dm, so destroying the dm calls destroy on the
419      vectors that cause another destroy on the dm
420   */
421   if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0);
422   ((PetscObject) (*dm))->refct = 0;
423   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
424     if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()");
425     ierr = VecDestroy(&(*dm)->localin[i]);CHKERRQ(ierr);
426   }
427   nnext=(*dm)->namedglobal;
428   (*dm)->namedglobal = NULL;
429   for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */
430     nnext = nlink->next;
431     if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
432     ierr = PetscFree(nlink->name);CHKERRQ(ierr);
433     ierr = VecDestroy(&nlink->X);CHKERRQ(ierr);
434     ierr = PetscFree(nlink);CHKERRQ(ierr);
435   }
436   nnext=(*dm)->namedlocal;
437   (*dm)->namedlocal = NULL;
438   for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */
439     nnext = nlink->next;
440     if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
441     ierr = PetscFree(nlink->name);CHKERRQ(ierr);
442     ierr = VecDestroy(&nlink->X);CHKERRQ(ierr);
443     ierr = PetscFree(nlink);CHKERRQ(ierr);
444   }
445 
446   /* Destroy the list of hooks */
447   {
448     DMCoarsenHookLink link,next;
449     for (link=(*dm)->coarsenhook; link; link=next) {
450       next = link->next;
451       ierr = PetscFree(link);CHKERRQ(ierr);
452     }
453     (*dm)->coarsenhook = NULL;
454   }
455   {
456     DMRefineHookLink link,next;
457     for (link=(*dm)->refinehook; link; link=next) {
458       next = link->next;
459       ierr = PetscFree(link);CHKERRQ(ierr);
460     }
461     (*dm)->refinehook = NULL;
462   }
463   {
464     DMSubDomainHookLink link,next;
465     for (link=(*dm)->subdomainhook; link; link=next) {
466       next = link->next;
467       ierr = PetscFree(link);CHKERRQ(ierr);
468     }
469     (*dm)->subdomainhook = NULL;
470   }
471   {
472     DMGlobalToLocalHookLink link,next;
473     for (link=(*dm)->gtolhook; link; link=next) {
474       next = link->next;
475       ierr = PetscFree(link);CHKERRQ(ierr);
476     }
477     (*dm)->gtolhook = NULL;
478   }
479   /* Destroy the work arrays */
480   {
481     DMWorkLink link,next;
482     if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out");
483     for (link=(*dm)->workin; link; link=next) {
484       next = link->next;
485       ierr = PetscFree(link->mem);CHKERRQ(ierr);
486       ierr = PetscFree(link);CHKERRQ(ierr);
487     }
488     (*dm)->workin = NULL;
489   }
490 
491   ierr = PetscObjectDestroy(&(*dm)->dmksp);CHKERRQ(ierr);
492   ierr = PetscObjectDestroy(&(*dm)->dmsnes);CHKERRQ(ierr);
493   ierr = PetscObjectDestroy(&(*dm)->dmts);CHKERRQ(ierr);
494 
495   if ((*dm)->ctx && (*dm)->ctxdestroy) {
496     ierr = (*(*dm)->ctxdestroy)(&(*dm)->ctx);CHKERRQ(ierr);
497   }
498   ierr = VecDestroy(&(*dm)->x);CHKERRQ(ierr);
499   ierr = MatFDColoringDestroy(&(*dm)->fd);CHKERRQ(ierr);
500   ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr);
501   ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr);
502   ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr);
503   ierr = PetscFree((*dm)->mattype);CHKERRQ(ierr);
504 
505   ierr = PetscSectionDestroy(&(*dm)->defaultSection);CHKERRQ(ierr);
506   ierr = PetscSectionDestroy(&(*dm)->defaultGlobalSection);CHKERRQ(ierr);
507   ierr = PetscLayoutDestroy(&(*dm)->map);CHKERRQ(ierr);
508   ierr = PetscSFDestroy(&(*dm)->sf);CHKERRQ(ierr);
509   ierr = PetscSFDestroy(&(*dm)->defaultSF);CHKERRQ(ierr);
510 
511   ierr = DMDestroy(&(*dm)->coordinateDM);CHKERRQ(ierr);
512   ierr = VecDestroy(&(*dm)->coordinates);CHKERRQ(ierr);
513   ierr = VecDestroy(&(*dm)->coordinatesLocal);CHKERRQ(ierr);
514   ierr = PetscFree((*dm)->maxCell);CHKERRQ(ierr);
515   ierr = PetscFree((*dm)->L);CHKERRQ(ierr);
516 
517   ierr = PetscDSDestroy(&(*dm)->prob);CHKERRQ(ierr);
518   ierr = DMDestroy(&(*dm)->dmBC);CHKERRQ(ierr);
519   /* if memory was published with SAWs then destroy it */
520   ierr = PetscObjectSAWsViewOff((PetscObject)*dm);CHKERRQ(ierr);
521 
522   ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr);
523   /* We do not destroy (*dm)->data here so that we can reference count backend objects */
524   ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr);
525   PetscFunctionReturn(0);
526 }
527 
528 #undef __FUNCT__
529 #define __FUNCT__ "DMSetUp"
530 /*@
531     DMSetUp - sets up the data structures inside a DM object
532 
533     Collective on DM
534 
535     Input Parameter:
536 .   dm - the DM object to setup
537 
538     Level: developer
539 
540 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
541 
542 @*/
543 PetscErrorCode  DMSetUp(DM dm)
544 {
545   PetscErrorCode ierr;
546 
547   PetscFunctionBegin;
548   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
549   if (dm->setupcalled) PetscFunctionReturn(0);
550   if (dm->ops->setup) {
551     ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr);
552   }
553   dm->setupcalled = PETSC_TRUE;
554   PetscFunctionReturn(0);
555 }
556 
557 #undef __FUNCT__
558 #define __FUNCT__ "DMSetFromOptions"
559 /*@
560     DMSetFromOptions - sets parameters in a DM from the options database
561 
562     Collective on DM
563 
564     Input Parameter:
565 .   dm - the DM object to set options for
566 
567     Options Database:
568 +   -dm_preallocate_only: Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros
569 .   -dm_vec_type <type>  type of vector to create inside DM
570 .   -dm_mat_type <type>  type of matrix to create inside DM
571 -   -dm_coloring_type <global or ghosted>
572 
573     Level: developer
574 
575 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
576 
577 @*/
578 PetscErrorCode  DMSetFromOptions(DM dm)
579 {
580   char           typeName[256];
581   PetscBool      flg;
582   PetscErrorCode ierr;
583 
584   PetscFunctionBegin;
585   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
586   ierr = PetscObjectOptionsBegin((PetscObject)dm);CHKERRQ(ierr);
587   ierr = PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);CHKERRQ(ierr);
588   ierr = PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);CHKERRQ(ierr);
589   if (flg) {
590     ierr = DMSetVecType(dm,typeName);CHKERRQ(ierr);
591   }
592   ierr = PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);CHKERRQ(ierr);
593   if (flg) {
594     ierr = DMSetMatType(dm,typeName);CHKERRQ(ierr);
595   }
596   ierr = PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","ISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);CHKERRQ(ierr);
597   if (dm->ops->setfromoptions) {
598     ierr = (*dm->ops->setfromoptions)(dm);CHKERRQ(ierr);
599   }
600   /* process any options handlers added with PetscObjectAddOptionsHandler() */
601   ierr = PetscObjectProcessOptionsHandlers((PetscObject) dm);CHKERRQ(ierr);
602   ierr = PetscOptionsEnd();CHKERRQ(ierr);
603   PetscFunctionReturn(0);
604 }
605 
606 #undef __FUNCT__
607 #define __FUNCT__ "DMView"
608 /*@C
609     DMView - Views a vector packer or DMDA.
610 
611     Collective on DM
612 
613     Input Parameter:
614 +   dm - the DM object to view
615 -   v - the viewer
616 
617     Level: developer
618 
619 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
620 
621 @*/
622 PetscErrorCode  DMView(DM dm,PetscViewer v)
623 {
624   PetscErrorCode ierr;
625   PetscBool      isbinary;
626 
627   PetscFunctionBegin;
628   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
629   if (!v) {
630     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);CHKERRQ(ierr);
631   }
632   ierr = PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);CHKERRQ(ierr);
633   ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
634   if (isbinary) {
635     PetscInt classid = DM_FILE_CLASSID;
636     char     type[256];
637 
638     ierr = PetscViewerBinaryWrite(v,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
639     ierr = PetscStrncpy(type,((PetscObject)dm)->type_name,256);CHKERRQ(ierr);
640     ierr = PetscViewerBinaryWrite(v,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
641   }
642   if (dm->ops->view) {
643     ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr);
644   }
645   PetscFunctionReturn(0);
646 }
647 
648 #undef __FUNCT__
649 #define __FUNCT__ "DMCreateGlobalVector"
650 /*@
651     DMCreateGlobalVector - Creates a global vector from a DMDA or DMComposite object
652 
653     Collective on DM
654 
655     Input Parameter:
656 .   dm - the DM object
657 
658     Output Parameter:
659 .   vec - the global vector
660 
661     Level: beginner
662 
663 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
664 
665 @*/
666 PetscErrorCode  DMCreateGlobalVector(DM dm,Vec *vec)
667 {
668   PetscErrorCode ierr;
669 
670   PetscFunctionBegin;
671   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
672   ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr);
673   PetscFunctionReturn(0);
674 }
675 
676 #undef __FUNCT__
677 #define __FUNCT__ "DMCreateLocalVector"
678 /*@
679     DMCreateLocalVector - Creates a local vector from a DMDA or DMComposite object
680 
681     Not Collective
682 
683     Input Parameter:
684 .   dm - the DM object
685 
686     Output Parameter:
687 .   vec - the local vector
688 
689     Level: beginner
690 
691 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
692 
693 @*/
694 PetscErrorCode  DMCreateLocalVector(DM dm,Vec *vec)
695 {
696   PetscErrorCode ierr;
697 
698   PetscFunctionBegin;
699   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
700   ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr);
701   PetscFunctionReturn(0);
702 }
703 
704 #undef __FUNCT__
705 #define __FUNCT__ "DMGetLocalToGlobalMapping"
706 /*@
707    DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM.
708 
709    Collective on DM
710 
711    Input Parameter:
712 .  dm - the DM that provides the mapping
713 
714    Output Parameter:
715 .  ltog - the mapping
716 
717    Level: intermediate
718 
719    Notes:
720    This mapping can then be used by VecSetLocalToGlobalMapping() or
721    MatSetLocalToGlobalMapping().
722 
723 .seealso: DMCreateLocalVector()
724 @*/
725 PetscErrorCode  DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog)
726 {
727   PetscErrorCode ierr;
728 
729   PetscFunctionBegin;
730   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
731   PetscValidPointer(ltog,2);
732   if (!dm->ltogmap) {
733     PetscSection section, sectionGlobal;
734 
735     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
736     if (section) {
737       PetscInt *ltog;
738       PetscInt pStart, pEnd, size, p, l;
739 
740       ierr = DMGetDefaultGlobalSection(dm, &sectionGlobal);CHKERRQ(ierr);
741       ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
742       ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
743       ierr = PetscMalloc1(size, &ltog);CHKERRQ(ierr); /* We want the local+overlap size */
744       for (p = pStart, l = 0; p < pEnd; ++p) {
745         PetscInt dof, off, c;
746 
747         /* Should probably use constrained dofs */
748         ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
749         ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr);
750         for (c = 0; c < dof; ++c, ++l) {
751           ltog[l] = off+c;
752         }
753       }
754       ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, 1,size, ltog, PETSC_OWN_POINTER, &dm->ltogmap);CHKERRQ(ierr);
755       ierr = PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);CHKERRQ(ierr);
756     } else {
757       if (!dm->ops->getlocaltoglobalmapping) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping");
758       ierr = (*dm->ops->getlocaltoglobalmapping)(dm);CHKERRQ(ierr);
759     }
760   }
761   *ltog = dm->ltogmap;
762   PetscFunctionReturn(0);
763 }
764 
765 #undef __FUNCT__
766 #define __FUNCT__ "DMGetBlockSize"
767 /*@
768    DMGetBlockSize - Gets the inherent block size associated with a DM
769 
770    Not Collective
771 
772    Input Parameter:
773 .  dm - the DM with block structure
774 
775    Output Parameter:
776 .  bs - the block size, 1 implies no exploitable block structure
777 
778    Level: intermediate
779 
780 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping()
781 @*/
782 PetscErrorCode  DMGetBlockSize(DM dm,PetscInt *bs)
783 {
784   PetscFunctionBegin;
785   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
786   PetscValidPointer(bs,2);
787   if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet");
788   *bs = dm->bs;
789   PetscFunctionReturn(0);
790 }
791 
792 #undef __FUNCT__
793 #define __FUNCT__ "DMCreateInterpolation"
794 /*@
795     DMCreateInterpolation - Gets interpolation matrix between two DMDA or DMComposite objects
796 
797     Collective on DM
798 
799     Input Parameter:
800 +   dm1 - the DM object
801 -   dm2 - the second, finer DM object
802 
803     Output Parameter:
804 +  mat - the interpolation
805 -  vec - the scaling (optional)
806 
807     Level: developer
808 
809     Notes:  For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
810         DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.
811 
812         For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors
813         EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
814 
815 
816 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen()
817 
818 @*/
819 PetscErrorCode  DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec)
820 {
821   PetscErrorCode ierr;
822 
823   PetscFunctionBegin;
824   PetscValidHeaderSpecific(dm1,DM_CLASSID,1);
825   PetscValidHeaderSpecific(dm2,DM_CLASSID,2);
826   ierr = (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);CHKERRQ(ierr);
827   PetscFunctionReturn(0);
828 }
829 
830 #undef __FUNCT__
831 #define __FUNCT__ "DMCreateInjection"
832 /*@
833     DMCreateInjection - Gets injection matrix between two DMDA or DMComposite objects
834 
835     Collective on DM
836 
837     Input Parameter:
838 +   dm1 - the DM object
839 -   dm2 - the second, finer DM object
840 
841     Output Parameter:
842 .   ctx - the injection
843 
844     Level: developer
845 
846    Notes:  For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
847         DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection.
848 
849 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation()
850 
851 @*/
852 PetscErrorCode  DMCreateInjection(DM dm1,DM dm2,VecScatter *ctx)
853 {
854   PetscErrorCode ierr;
855 
856   PetscFunctionBegin;
857   PetscValidHeaderSpecific(dm1,DM_CLASSID,1);
858   PetscValidHeaderSpecific(dm2,DM_CLASSID,2);
859   ierr = (*dm1->ops->getinjection)(dm1,dm2,ctx);CHKERRQ(ierr);
860   PetscFunctionReturn(0);
861 }
862 
863 #undef __FUNCT__
864 #define __FUNCT__ "DMCreateColoring"
865 /*@
866     DMCreateColoring - Gets coloring for a DM
867 
868     Collective on DM
869 
870     Input Parameter:
871 +   dm - the DM object
872 -   ctype - IS_COLORING_GHOSTED or IS_COLORING_GLOBAL
873 
874     Output Parameter:
875 .   coloring - the coloring
876 
877     Level: developer
878 
879 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType()
880 
881 @*/
882 PetscErrorCode  DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring)
883 {
884   PetscErrorCode ierr;
885 
886   PetscFunctionBegin;
887   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
888   if (!dm->ops->getcoloring) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No coloring for this type of DM yet");
889   ierr = (*dm->ops->getcoloring)(dm,ctype,coloring);CHKERRQ(ierr);
890   PetscFunctionReturn(0);
891 }
892 
893 #undef __FUNCT__
894 #define __FUNCT__ "DMCreateMatrix"
895 /*@
896     DMCreateMatrix - Gets empty Jacobian for a DMDA or DMComposite
897 
898     Collective on DM
899 
900     Input Parameter:
901 .   dm - the DM object
902 
903     Output Parameter:
904 .   mat - the empty Jacobian
905 
906     Level: beginner
907 
908     Notes: This properly preallocates the number of nonzeros in the sparse matrix so you
909        do not need to do it yourself.
910 
911        By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
912        the nonzero pattern call DMDASetMatPreallocateOnly()
913 
914        For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used
915        internally by PETSc.
916 
917        For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires
918        the indices for the global numbering for DMDAs which is complicated.
919 
920 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType()
921 
922 @*/
923 PetscErrorCode  DMCreateMatrix(DM dm,Mat *mat)
924 {
925   PetscErrorCode ierr;
926 
927   PetscFunctionBegin;
928   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
929   ierr = MatInitializePackage();CHKERRQ(ierr);
930   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
931   PetscValidPointer(mat,3);
932   ierr = (*dm->ops->creatematrix)(dm,mat);CHKERRQ(ierr);
933   PetscFunctionReturn(0);
934 }
935 
936 #undef __FUNCT__
937 #define __FUNCT__ "DMSetMatrixPreallocateOnly"
938 /*@
939   DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly
940     preallocated but the nonzero structure and zero values will not be set.
941 
942   Logically Collective on DMDA
943 
944   Input Parameter:
945 + dm - the DM
946 - only - PETSC_TRUE if only want preallocation
947 
948   Level: developer
949 .seealso DMCreateMatrix()
950 @*/
951 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
952 {
953   PetscFunctionBegin;
954   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
955   dm->prealloc_only = only;
956   PetscFunctionReturn(0);
957 }
958 
959 #undef __FUNCT__
960 #define __FUNCT__ "DMGetWorkArray"
961 /*@C
962   DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
963 
964   Not Collective
965 
966   Input Parameters:
967 + dm - the DM object
968 . count - The minium size
969 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT)
970 
971   Output Parameter:
972 . array - the work array
973 
974   Level: developer
975 
976 .seealso DMDestroy(), DMCreate()
977 @*/
978 PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem)
979 {
980   PetscErrorCode ierr;
981   DMWorkLink     link;
982   size_t         size;
983 
984   PetscFunctionBegin;
985   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
986   PetscValidPointer(mem,4);
987   if (dm->workin) {
988     link       = dm->workin;
989     dm->workin = dm->workin->next;
990   } else {
991     ierr = PetscNewLog(dm,&link);CHKERRQ(ierr);
992   }
993   ierr = PetscDataTypeGetSize(dtype,&size);CHKERRQ(ierr);
994   if (size*count > link->bytes) {
995     ierr        = PetscFree(link->mem);CHKERRQ(ierr);
996     ierr        = PetscMalloc(size*count,&link->mem);CHKERRQ(ierr);
997     link->bytes = size*count;
998   }
999   link->next   = dm->workout;
1000   dm->workout  = link;
1001   *(void**)mem = link->mem;
1002   PetscFunctionReturn(0);
1003 }
1004 
1005 #undef __FUNCT__
1006 #define __FUNCT__ "DMRestoreWorkArray"
1007 /*@C
1008   DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1009 
1010   Not Collective
1011 
1012   Input Parameters:
1013 + dm - the DM object
1014 . count - The minium size
1015 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT)
1016 
1017   Output Parameter:
1018 . array - the work array
1019 
1020   Level: developer
1021 
1022 .seealso DMDestroy(), DMCreate()
1023 @*/
1024 PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem)
1025 {
1026   DMWorkLink *p,link;
1027 
1028   PetscFunctionBegin;
1029   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1030   PetscValidPointer(mem,4);
1031   for (p=&dm->workout; (link=*p); p=&link->next) {
1032     if (link->mem == *(void**)mem) {
1033       *p           = link->next;
1034       link->next   = dm->workin;
1035       dm->workin   = link;
1036       *(void**)mem = NULL;
1037       PetscFunctionReturn(0);
1038     }
1039   }
1040   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out");
1041   PetscFunctionReturn(0);
1042 }
1043 
1044 #undef __FUNCT__
1045 #define __FUNCT__ "DMSetNullSpaceConstructor"
1046 PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace))
1047 {
1048   PetscFunctionBegin;
1049   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1050   if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1051   dm->nullspaceConstructors[field] = nullsp;
1052   PetscFunctionReturn(0);
1053 }
1054 
1055 #undef __FUNCT__
1056 #define __FUNCT__ "DMCreateFieldIS"
1057 /*@C
1058   DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field
1059 
1060   Not collective
1061 
1062   Input Parameter:
1063 . dm - the DM object
1064 
1065   Output Parameters:
1066 + numFields  - The number of fields (or NULL if not requested)
1067 . fieldNames - The name for each field (or NULL if not requested)
1068 - fields     - The global indices for each field (or NULL if not requested)
1069 
1070   Level: intermediate
1071 
1072   Notes:
1073   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1074   PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with
1075   PetscFree().
1076 
1077 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
1078 @*/
1079 PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1080 {
1081   PetscSection   section, sectionGlobal;
1082   PetscErrorCode ierr;
1083 
1084   PetscFunctionBegin;
1085   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1086   if (numFields) {
1087     PetscValidPointer(numFields,2);
1088     *numFields = 0;
1089   }
1090   if (fieldNames) {
1091     PetscValidPointer(fieldNames,3);
1092     *fieldNames = NULL;
1093   }
1094   if (fields) {
1095     PetscValidPointer(fields,4);
1096     *fields = NULL;
1097   }
1098   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
1099   if (section) {
1100     PetscInt *fieldSizes, **fieldIndices;
1101     PetscInt nF, f, pStart, pEnd, p;
1102 
1103     ierr = DMGetDefaultGlobalSection(dm, &sectionGlobal);CHKERRQ(ierr);
1104     ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr);
1105     ierr = PetscMalloc2(nF,&fieldSizes,nF,&fieldIndices);CHKERRQ(ierr);
1106     ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr);
1107     for (f = 0; f < nF; ++f) {
1108       fieldSizes[f] = 0;
1109     }
1110     for (p = pStart; p < pEnd; ++p) {
1111       PetscInt gdof;
1112 
1113       ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr);
1114       if (gdof > 0) {
1115         for (f = 0; f < nF; ++f) {
1116           PetscInt fdof, fcdof;
1117 
1118           ierr           = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr);
1119           ierr           = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr);
1120           fieldSizes[f] += fdof-fcdof;
1121         }
1122       }
1123     }
1124     for (f = 0; f < nF; ++f) {
1125       ierr          = PetscMalloc1(fieldSizes[f], &fieldIndices[f]);CHKERRQ(ierr);
1126       fieldSizes[f] = 0;
1127     }
1128     for (p = pStart; p < pEnd; ++p) {
1129       PetscInt gdof, goff;
1130 
1131       ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr);
1132       if (gdof > 0) {
1133         ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr);
1134         for (f = 0; f < nF; ++f) {
1135           PetscInt fdof, fcdof, fc;
1136 
1137           ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr);
1138           ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr);
1139           for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) {
1140             fieldIndices[f][fieldSizes[f]] = goff++;
1141           }
1142         }
1143       }
1144     }
1145     if (numFields) *numFields = nF;
1146     if (fieldNames) {
1147       ierr = PetscMalloc1(nF, fieldNames);CHKERRQ(ierr);
1148       for (f = 0; f < nF; ++f) {
1149         const char *fieldName;
1150 
1151         ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr);
1152         ierr = PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);CHKERRQ(ierr);
1153       }
1154     }
1155     if (fields) {
1156       ierr = PetscMalloc1(nF, fields);CHKERRQ(ierr);
1157       for (f = 0; f < nF; ++f) {
1158         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);CHKERRQ(ierr);
1159       }
1160     }
1161     ierr = PetscFree2(fieldSizes,fieldIndices);CHKERRQ(ierr);
1162   } else if (dm->ops->createfieldis) {
1163     ierr = (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);CHKERRQ(ierr);
1164   }
1165   PetscFunctionReturn(0);
1166 }
1167 
1168 
1169 #undef __FUNCT__
1170 #define __FUNCT__ "DMCreateFieldDecomposition"
1171 /*@C
1172   DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems
1173                           corresponding to different fields: each IS contains the global indices of the dofs of the
1174                           corresponding field. The optional list of DMs define the DM for each subproblem.
1175                           Generalizes DMCreateFieldIS().
1176 
1177   Not collective
1178 
1179   Input Parameter:
1180 . dm - the DM object
1181 
1182   Output Parameters:
1183 + len       - The number of subproblems in the field decomposition (or NULL if not requested)
1184 . namelist  - The name for each field (or NULL if not requested)
1185 . islist    - The global indices for each field (or NULL if not requested)
1186 - dmlist    - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1187 
1188   Level: intermediate
1189 
1190   Notes:
1191   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1192   PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1193   and all of the arrays should be freed with PetscFree().
1194 
1195 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1196 @*/
1197 PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
1198 {
1199   PetscErrorCode ierr;
1200 
1201   PetscFunctionBegin;
1202   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1203   if (len) {
1204     PetscValidPointer(len,2);
1205     *len = 0;
1206   }
1207   if (namelist) {
1208     PetscValidPointer(namelist,3);
1209     *namelist = 0;
1210   }
1211   if (islist) {
1212     PetscValidPointer(islist,4);
1213     *islist = 0;
1214   }
1215   if (dmlist) {
1216     PetscValidPointer(dmlist,5);
1217     *dmlist = 0;
1218   }
1219   /*
1220    Is it a good idea to apply the following check across all impls?
1221    Perhaps some impls can have a well-defined decomposition before DMSetUp?
1222    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1223    */
1224   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1225   if (!dm->ops->createfielddecomposition) {
1226     PetscSection section;
1227     PetscInt     numFields, f;
1228 
1229     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
1230     if (section) {ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);}
1231     if (section && numFields && dm->ops->createsubdm) {
1232       *len = numFields;
1233       if (namelist) {ierr = PetscMalloc1(numFields,namelist);CHKERRQ(ierr);}
1234       if (islist)   {ierr = PetscMalloc1(numFields,islist);CHKERRQ(ierr);}
1235       if (dmlist)   {ierr = PetscMalloc1(numFields,dmlist);CHKERRQ(ierr);}
1236       for (f = 0; f < numFields; ++f) {
1237         const char *fieldName;
1238 
1239         ierr = DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);CHKERRQ(ierr);
1240         if (namelist) {
1241           ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr);
1242           ierr = PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);CHKERRQ(ierr);
1243         }
1244       }
1245     } else {
1246       ierr = DMCreateFieldIS(dm, len, namelist, islist);CHKERRQ(ierr);
1247       /* By default there are no DMs associated with subproblems. */
1248       if (dmlist) *dmlist = NULL;
1249     }
1250   } else {
1251     ierr = (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);CHKERRQ(ierr);
1252   }
1253   PetscFunctionReturn(0);
1254 }
1255 
1256 #undef __FUNCT__
1257 #define __FUNCT__ "DMCreateSubDM"
1258 /*@C
1259   DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in.
1260                   The fields are defined by DMCreateFieldIS().
1261 
1262   Not collective
1263 
1264   Input Parameters:
1265 + dm - the DM object
1266 . numFields - number of fields in this subproblem
1267 - len       - The number of subproblems in the decomposition (or NULL if not requested)
1268 
1269   Output Parameters:
1270 . is - The global indices for the subproblem
1271 - dm - The DM for the subproblem
1272 
1273   Level: intermediate
1274 
1275 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1276 @*/
1277 PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
1278 {
1279   PetscErrorCode ierr;
1280 
1281   PetscFunctionBegin;
1282   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1283   PetscValidPointer(fields,3);
1284   if (is) PetscValidPointer(is,4);
1285   if (subdm) PetscValidPointer(subdm,5);
1286   if (dm->ops->createsubdm) {
1287     ierr = (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);CHKERRQ(ierr);
1288   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined");
1289   PetscFunctionReturn(0);
1290 }
1291 
1292 
1293 #undef __FUNCT__
1294 #define __FUNCT__ "DMCreateDomainDecomposition"
1295 /*@C
1296   DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems
1297                           corresponding to restrictions to pairs nested subdomains: each IS contains the global
1298                           indices of the dofs of the corresponding subdomains.  The inner subdomains conceptually
1299                           define a nonoverlapping covering, while outer subdomains can overlap.
1300                           The optional list of DMs define the DM for each subproblem.
1301 
1302   Not collective
1303 
1304   Input Parameter:
1305 . dm - the DM object
1306 
1307   Output Parameters:
1308 + len         - The number of subproblems in the domain decomposition (or NULL if not requested)
1309 . namelist    - The name for each subdomain (or NULL if not requested)
1310 . innerislist - The global indices for each inner subdomain (or NULL, if not requested)
1311 . outerislist - The global indices for each outer subdomain (or NULL, if not requested)
1312 - dmlist      - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1313 
1314   Level: intermediate
1315 
1316   Notes:
1317   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1318   PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1319   and all of the arrays should be freed with PetscFree().
1320 
1321 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition()
1322 @*/
1323 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
1324 {
1325   PetscErrorCode      ierr;
1326   DMSubDomainHookLink link;
1327   PetscInt            i,l;
1328 
1329   PetscFunctionBegin;
1330   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1331   if (len)           {PetscValidPointer(len,2);            *len         = 0;}
1332   if (namelist)      {PetscValidPointer(namelist,3);       *namelist    = NULL;}
1333   if (innerislist)   {PetscValidPointer(innerislist,4);    *innerislist = NULL;}
1334   if (outerislist)   {PetscValidPointer(outerislist,5);    *outerislist = NULL;}
1335   if (dmlist)        {PetscValidPointer(dmlist,6);         *dmlist      = NULL;}
1336   /*
1337    Is it a good idea to apply the following check across all impls?
1338    Perhaps some impls can have a well-defined decomposition before DMSetUp?
1339    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1340    */
1341   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1342   if (dm->ops->createdomaindecomposition) {
1343     ierr = (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);CHKERRQ(ierr);
1344     /* copy subdomain hooks and context over to the subdomain DMs */
1345     if (dmlist) {
1346       for (i = 0; i < l; i++) {
1347         for (link=dm->subdomainhook; link; link=link->next) {
1348           if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);}
1349         }
1350         (*dmlist)[i]->ctx = dm->ctx;
1351       }
1352     }
1353     if (len) *len = l;
1354   }
1355   PetscFunctionReturn(0);
1356 }
1357 
1358 
1359 #undef __FUNCT__
1360 #define __FUNCT__ "DMCreateDomainDecompositionScatters"
1361 /*@C
1362   DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector
1363 
1364   Not collective
1365 
1366   Input Parameters:
1367 + dm - the DM object
1368 . n  - the number of subdomain scatters
1369 - subdms - the local subdomains
1370 
1371   Output Parameters:
1372 + n     - the number of scatters returned
1373 . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain
1374 . oscat - scatter from global vector to overlapping global vector entries on subdomain
1375 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts)
1376 
1377   Notes: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution
1378   of general nonlinear problems with overlapping subdomain methods.  While merely having index sets that enable subsets
1379   of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of
1380   solution and residual data.
1381 
1382   Level: developer
1383 
1384 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1385 @*/
1386 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat)
1387 {
1388   PetscErrorCode ierr;
1389 
1390   PetscFunctionBegin;
1391   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1392   PetscValidPointer(subdms,3);
1393   if (dm->ops->createddscatters) {
1394     ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr);
1395   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionLocalScatter implementation defined");
1396   PetscFunctionReturn(0);
1397 }
1398 
1399 #undef __FUNCT__
1400 #define __FUNCT__ "DMRefine"
1401 /*@
1402   DMRefine - Refines a DM object
1403 
1404   Collective on DM
1405 
1406   Input Parameter:
1407 + dm   - the DM object
1408 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
1409 
1410   Output Parameter:
1411 . dmf - the refined DM, or NULL
1412 
1413   Note: If no refinement was done, the return value is NULL
1414 
1415   Level: developer
1416 
1417 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1418 @*/
1419 PetscErrorCode  DMRefine(DM dm,MPI_Comm comm,DM *dmf)
1420 {
1421   PetscErrorCode   ierr;
1422   DMRefineHookLink link;
1423 
1424   PetscFunctionBegin;
1425   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1426   ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr);
1427   if (*dmf) {
1428     (*dmf)->ops->creatematrix = dm->ops->creatematrix;
1429 
1430     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr);
1431 
1432     (*dmf)->ctx       = dm->ctx;
1433     (*dmf)->leveldown = dm->leveldown;
1434     (*dmf)->levelup   = dm->levelup + 1;
1435 
1436     ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr);
1437     for (link=dm->refinehook; link; link=link->next) {
1438       if (link->refinehook) {
1439         ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr);
1440       }
1441     }
1442   }
1443   PetscFunctionReturn(0);
1444 }
1445 
1446 #undef __FUNCT__
1447 #define __FUNCT__ "DMRefineHookAdd"
1448 /*@C
1449    DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid
1450 
1451    Logically Collective
1452 
1453    Input Arguments:
1454 +  coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
1455 .  refinehook - function to run when setting up a coarser level
1456 .  interphook - function to run to update data on finer levels (once per SNESSolve())
1457 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1458 
1459    Calling sequence of refinehook:
1460 $    refinehook(DM coarse,DM fine,void *ctx);
1461 
1462 +  coarse - coarse level DM
1463 .  fine - fine level DM to interpolate problem to
1464 -  ctx - optional user-defined function context
1465 
1466    Calling sequence for interphook:
1467 $    interphook(DM coarse,Mat interp,DM fine,void *ctx)
1468 
1469 +  coarse - coarse level DM
1470 .  interp - matrix interpolating a coarse-level solution to the finer grid
1471 .  fine - fine level DM to update
1472 -  ctx - optional user-defined function context
1473 
1474    Level: advanced
1475 
1476    Notes:
1477    This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing
1478 
1479    If this function is called multiple times, the hooks will be run in the order they are added.
1480 
1481    This function is currently not available from Fortran.
1482 
1483 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1484 @*/
1485 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
1486 {
1487   PetscErrorCode   ierr;
1488   DMRefineHookLink link,*p;
1489 
1490   PetscFunctionBegin;
1491   PetscValidHeaderSpecific(coarse,DM_CLASSID,1);
1492   for (p=&coarse->refinehook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
1493   ierr             = PetscMalloc(sizeof(struct _DMRefineHookLink),&link);CHKERRQ(ierr);
1494   link->refinehook = refinehook;
1495   link->interphook = interphook;
1496   link->ctx        = ctx;
1497   link->next       = NULL;
1498   *p               = link;
1499   PetscFunctionReturn(0);
1500 }
1501 
1502 #undef __FUNCT__
1503 #define __FUNCT__ "DMInterpolate"
1504 /*@
1505    DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd()
1506 
1507    Collective if any hooks are
1508 
1509    Input Arguments:
1510 +  coarse - coarser DM to use as a base
1511 .  restrct - interpolation matrix, apply using MatInterpolate()
1512 -  fine - finer DM to update
1513 
1514    Level: developer
1515 
1516 .seealso: DMRefineHookAdd(), MatInterpolate()
1517 @*/
1518 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine)
1519 {
1520   PetscErrorCode   ierr;
1521   DMRefineHookLink link;
1522 
1523   PetscFunctionBegin;
1524   for (link=fine->refinehook; link; link=link->next) {
1525     if (link->interphook) {
1526       ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr);
1527     }
1528   }
1529   PetscFunctionReturn(0);
1530 }
1531 
1532 #undef __FUNCT__
1533 #define __FUNCT__ "DMGetRefineLevel"
1534 /*@
1535     DMGetRefineLevel - Get's the number of refinements that have generated this DM.
1536 
1537     Not Collective
1538 
1539     Input Parameter:
1540 .   dm - the DM object
1541 
1542     Output Parameter:
1543 .   level - number of refinements
1544 
1545     Level: developer
1546 
1547 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1548 
1549 @*/
1550 PetscErrorCode  DMGetRefineLevel(DM dm,PetscInt *level)
1551 {
1552   PetscFunctionBegin;
1553   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1554   *level = dm->levelup;
1555   PetscFunctionReturn(0);
1556 }
1557 
1558 #undef __FUNCT__
1559 #define __FUNCT__ "DMGlobalToLocalHookAdd"
1560 /*@C
1561    DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called
1562 
1563    Logically Collective
1564 
1565    Input Arguments:
1566 +  dm - the DM
1567 .  beginhook - function to run at the beginning of DMGlobalToLocalBegin()
1568 .  endhook - function to run after DMGlobalToLocalEnd() has completed
1569 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1570 
1571    Calling sequence for beginhook:
1572 $    beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
1573 
1574 +  dm - global DM
1575 .  g - global vector
1576 .  mode - mode
1577 .  l - local vector
1578 -  ctx - optional user-defined function context
1579 
1580 
1581    Calling sequence for endhook:
1582 $    endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
1583 
1584 +  global - global DM
1585 -  ctx - optional user-defined function context
1586 
1587    Level: advanced
1588 
1589 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1590 @*/
1591 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
1592 {
1593   PetscErrorCode          ierr;
1594   DMGlobalToLocalHookLink link,*p;
1595 
1596   PetscFunctionBegin;
1597   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1598   for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
1599   ierr            = PetscMalloc(sizeof(struct _DMGlobalToLocalHookLink),&link);CHKERRQ(ierr);
1600   link->beginhook = beginhook;
1601   link->endhook   = endhook;
1602   link->ctx       = ctx;
1603   link->next      = NULL;
1604   *p              = link;
1605   PetscFunctionReturn(0);
1606 }
1607 
1608 #undef __FUNCT__
1609 #define __FUNCT__ "DMGlobalToLocalBegin"
1610 /*@
1611     DMGlobalToLocalBegin - Begins updating local vectors from global vector
1612 
1613     Neighbor-wise Collective on DM
1614 
1615     Input Parameters:
1616 +   dm - the DM object
1617 .   g - the global vector
1618 .   mode - INSERT_VALUES or ADD_VALUES
1619 -   l - the local vector
1620 
1621 
1622     Level: beginner
1623 
1624 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
1625 
1626 @*/
1627 PetscErrorCode  DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
1628 {
1629   PetscSF                 sf;
1630   PetscErrorCode          ierr;
1631   DMGlobalToLocalHookLink link;
1632 
1633   PetscFunctionBegin;
1634   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1635   for (link=dm->gtolhook; link; link=link->next) {
1636     if (link->beginhook) {
1637       ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);
1638     }
1639   }
1640   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1641   if (sf) {
1642     PetscScalar *lArray, *gArray;
1643 
1644     if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1645     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1646     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
1647     ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr);
1648     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1649     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
1650   } else {
1651     ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
1652   }
1653   PetscFunctionReturn(0);
1654 }
1655 
1656 #undef __FUNCT__
1657 #define __FUNCT__ "DMGlobalToLocalEnd"
1658 /*@
1659     DMGlobalToLocalEnd - Ends updating local vectors from global vector
1660 
1661     Neighbor-wise Collective on DM
1662 
1663     Input Parameters:
1664 +   dm - the DM object
1665 .   g - the global vector
1666 .   mode - INSERT_VALUES or ADD_VALUES
1667 -   l - the local vector
1668 
1669 
1670     Level: beginner
1671 
1672 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
1673 
1674 @*/
1675 PetscErrorCode  DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
1676 {
1677   PetscSF                 sf;
1678   PetscErrorCode          ierr;
1679   PetscScalar             *lArray, *gArray;
1680   DMGlobalToLocalHookLink link;
1681 
1682   PetscFunctionBegin;
1683   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1684   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1685   if (sf) {
1686     if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1687 
1688     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1689     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
1690     ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr);
1691     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1692     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
1693   } else {
1694     ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
1695   }
1696   for (link=dm->gtolhook; link; link=link->next) {
1697     if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);}
1698   }
1699   PetscFunctionReturn(0);
1700 }
1701 
1702 #undef __FUNCT__
1703 #define __FUNCT__ "DMLocalToGlobalBegin"
1704 /*@
1705     DMLocalToGlobalBegin - updates global vectors from local vectors
1706 
1707     Neighbor-wise Collective on DM
1708 
1709     Input Parameters:
1710 +   dm - the DM object
1711 .   l - the local vector
1712 .   mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that
1713            base point.
1714 - - the global vector
1715 
1716     Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. If you would like to simply add the non-ghosted values in the local
1717            array into the global array you need to either (1) zero the ghosted locations and use ADD_VALUES or (2) use INSERT_VALUES into a work global array and then add the work
1718            global array to the final global array with VecAXPY().
1719 
1720     Level: beginner
1721 
1722 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()
1723 
1724 @*/
1725 PetscErrorCode  DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
1726 {
1727   PetscSF        sf;
1728   PetscErrorCode ierr;
1729 
1730   PetscFunctionBegin;
1731   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1732   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1733   if (sf) {
1734     MPI_Op      op;
1735     PetscScalar *lArray, *gArray;
1736 
1737     switch (mode) {
1738     case INSERT_VALUES:
1739     case INSERT_ALL_VALUES:
1740       op = MPIU_REPLACE; break;
1741     case ADD_VALUES:
1742     case ADD_ALL_VALUES:
1743       op = MPI_SUM; break;
1744     default:
1745       SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1746     }
1747     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1748     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
1749     ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, op);CHKERRQ(ierr);
1750     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1751     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
1752   } else {
1753     ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr);
1754   }
1755   PetscFunctionReturn(0);
1756 }
1757 
1758 #undef __FUNCT__
1759 #define __FUNCT__ "DMLocalToGlobalEnd"
1760 /*@
1761     DMLocalToGlobalEnd - updates global vectors from local vectors
1762 
1763     Neighbor-wise Collective on DM
1764 
1765     Input Parameters:
1766 +   dm - the DM object
1767 .   l - the local vector
1768 .   mode - INSERT_VALUES or ADD_VALUES
1769 -   g - the global vector
1770 
1771 
1772     Level: beginner
1773 
1774 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()
1775 
1776 @*/
1777 PetscErrorCode  DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
1778 {
1779   PetscSF        sf;
1780   PetscErrorCode ierr;
1781 
1782   PetscFunctionBegin;
1783   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1784   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1785   if (sf) {
1786     MPI_Op      op;
1787     PetscScalar *lArray, *gArray;
1788 
1789     switch (mode) {
1790     case INSERT_VALUES:
1791     case INSERT_ALL_VALUES:
1792       op = MPIU_REPLACE; break;
1793     case ADD_VALUES:
1794     case ADD_ALL_VALUES:
1795       op = MPI_SUM; break;
1796     default:
1797       SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1798     }
1799     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1800     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
1801     ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, op);CHKERRQ(ierr);
1802     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1803     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
1804   } else {
1805     ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr);
1806   }
1807   PetscFunctionReturn(0);
1808 }
1809 
1810 #undef __FUNCT__
1811 #define __FUNCT__ "DMLocalToLocalBegin"
1812 /*@
1813    DMLocalToLocalBegin - Maps from a local vector (including ghost points
1814    that contain irrelevant values) to another local vector where the ghost
1815    points in the second are set correctly. Must be followed by DMLocalToLocalEnd().
1816 
1817    Neighbor-wise Collective on DM and Vec
1818 
1819    Input Parameters:
1820 +  dm - the DM object
1821 .  g - the original local vector
1822 -  mode - one of INSERT_VALUES or ADD_VALUES
1823 
1824    Output Parameter:
1825 .  l  - the local vector with correct ghost values
1826 
1827    Level: intermediate
1828 
1829    Notes:
1830    The local vectors used here need not be the same as those
1831    obtained from DMCreateLocalVector(), BUT they
1832    must have the same parallel data layout; they could, for example, be
1833    obtained with VecDuplicate() from the DM originating vectors.
1834 
1835 .keywords: DM, local-to-local, begin
1836 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
1837 
1838 @*/
1839 PetscErrorCode  DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
1840 {
1841   PetscErrorCode          ierr;
1842 
1843   PetscFunctionBegin;
1844   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1845   ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
1846   PetscFunctionReturn(0);
1847 }
1848 
1849 #undef __FUNCT__
1850 #define __FUNCT__ "DMLocalToLocalEnd"
1851 /*@
1852    DMLocalToLocalEnd - Maps from a local vector (including ghost points
1853    that contain irrelevant values) to another local vector where the ghost
1854    points in the second are set correctly. Must be preceded by DMLocalToLocalBegin().
1855 
1856    Neighbor-wise Collective on DM and Vec
1857 
1858    Input Parameters:
1859 +  da - the DM object
1860 .  g - the original local vector
1861 -  mode - one of INSERT_VALUES or ADD_VALUES
1862 
1863    Output Parameter:
1864 .  l  - the local vector with correct ghost values
1865 
1866    Level: intermediate
1867 
1868    Notes:
1869    The local vectors used here need not be the same as those
1870    obtained from DMCreateLocalVector(), BUT they
1871    must have the same parallel data layout; they could, for example, be
1872    obtained with VecDuplicate() from the DM originating vectors.
1873 
1874 .keywords: DM, local-to-local, end
1875 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
1876 
1877 @*/
1878 PetscErrorCode  DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
1879 {
1880   PetscErrorCode          ierr;
1881 
1882   PetscFunctionBegin;
1883   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1884   ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
1885   PetscFunctionReturn(0);
1886 }
1887 
1888 
1889 #undef __FUNCT__
1890 #define __FUNCT__ "DMCoarsen"
1891 /*@
1892     DMCoarsen - Coarsens a DM object
1893 
1894     Collective on DM
1895 
1896     Input Parameter:
1897 +   dm - the DM object
1898 -   comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
1899 
1900     Output Parameter:
1901 .   dmc - the coarsened DM
1902 
1903     Level: developer
1904 
1905 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1906 
1907 @*/
1908 PetscErrorCode  DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
1909 {
1910   PetscErrorCode    ierr;
1911   DMCoarsenHookLink link;
1912 
1913   PetscFunctionBegin;
1914   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1915   ierr                      = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr);
1916   (*dmc)->ops->creatematrix = dm->ops->creatematrix;
1917   ierr                      = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr);
1918   (*dmc)->ctx               = dm->ctx;
1919   (*dmc)->levelup           = dm->levelup;
1920   (*dmc)->leveldown         = dm->leveldown + 1;
1921   ierr                      = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr);
1922   for (link=dm->coarsenhook; link; link=link->next) {
1923     if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);}
1924   }
1925   PetscFunctionReturn(0);
1926 }
1927 
1928 #undef __FUNCT__
1929 #define __FUNCT__ "DMCoarsenHookAdd"
1930 /*@C
1931    DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
1932 
1933    Logically Collective
1934 
1935    Input Arguments:
1936 +  fine - nonlinear solver context on which to run a hook when restricting to a coarser level
1937 .  coarsenhook - function to run when setting up a coarser level
1938 .  restricthook - function to run to update data on coarser levels (once per SNESSolve())
1939 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1940 
1941    Calling sequence of coarsenhook:
1942 $    coarsenhook(DM fine,DM coarse,void *ctx);
1943 
1944 +  fine - fine level DM
1945 .  coarse - coarse level DM to restrict problem to
1946 -  ctx - optional user-defined function context
1947 
1948    Calling sequence for restricthook:
1949 $    restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx)
1950 
1951 +  fine - fine level DM
1952 .  mrestrict - matrix restricting a fine-level solution to the coarse grid
1953 .  rscale - scaling vector for restriction
1954 .  inject - matrix restricting by injection
1955 .  coarse - coarse level DM to update
1956 -  ctx - optional user-defined function context
1957 
1958    Level: advanced
1959 
1960    Notes:
1961    This function is only needed if auxiliary data needs to be set up on coarse grids.
1962 
1963    If this function is called multiple times, the hooks will be run in the order they are added.
1964 
1965    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
1966    extract the finest level information from its context (instead of from the SNES).
1967 
1968    This function is currently not available from Fortran.
1969 
1970 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1971 @*/
1972 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
1973 {
1974   PetscErrorCode    ierr;
1975   DMCoarsenHookLink link,*p;
1976 
1977   PetscFunctionBegin;
1978   PetscValidHeaderSpecific(fine,DM_CLASSID,1);
1979   for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
1980   ierr               = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&link);CHKERRQ(ierr);
1981   link->coarsenhook  = coarsenhook;
1982   link->restricthook = restricthook;
1983   link->ctx          = ctx;
1984   link->next         = NULL;
1985   *p                 = link;
1986   PetscFunctionReturn(0);
1987 }
1988 
1989 #undef __FUNCT__
1990 #define __FUNCT__ "DMRestrict"
1991 /*@
1992    DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd()
1993 
1994    Collective if any hooks are
1995 
1996    Input Arguments:
1997 +  fine - finer DM to use as a base
1998 .  restrct - restriction matrix, apply using MatRestrict()
1999 .  inject - injection matrix, also use MatRestrict()
2000 -  coarse - coarer DM to update
2001 
2002    Level: developer
2003 
2004 .seealso: DMCoarsenHookAdd(), MatRestrict()
2005 @*/
2006 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse)
2007 {
2008   PetscErrorCode    ierr;
2009   DMCoarsenHookLink link;
2010 
2011   PetscFunctionBegin;
2012   for (link=fine->coarsenhook; link; link=link->next) {
2013     if (link->restricthook) {
2014       ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr);
2015     }
2016   }
2017   PetscFunctionReturn(0);
2018 }
2019 
2020 #undef __FUNCT__
2021 #define __FUNCT__ "DMSubDomainHookAdd"
2022 /*@C
2023    DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
2024 
2025    Logically Collective
2026 
2027    Input Arguments:
2028 +  global - global DM
2029 .  ddhook - function to run to pass data to the decomposition DM upon its creation
2030 .  restricthook - function to run to update data on block solve (at the beginning of the block solve)
2031 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2032 
2033 
2034    Calling sequence for ddhook:
2035 $    ddhook(DM global,DM block,void *ctx)
2036 
2037 +  global - global DM
2038 .  block  - block DM
2039 -  ctx - optional user-defined function context
2040 
2041    Calling sequence for restricthook:
2042 $    restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx)
2043 
2044 +  global - global DM
2045 .  out    - scatter to the outer (with ghost and overlap points) block vector
2046 .  in     - scatter to block vector values only owned locally
2047 .  block  - block DM
2048 -  ctx - optional user-defined function context
2049 
2050    Level: advanced
2051 
2052    Notes:
2053    This function is only needed if auxiliary data needs to be set up on subdomain DMs.
2054 
2055    If this function is called multiple times, the hooks will be run in the order they are added.
2056 
2057    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2058    extract the global information from its context (instead of from the SNES).
2059 
2060    This function is currently not available from Fortran.
2061 
2062 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2063 @*/
2064 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
2065 {
2066   PetscErrorCode      ierr;
2067   DMSubDomainHookLink link,*p;
2068 
2069   PetscFunctionBegin;
2070   PetscValidHeaderSpecific(global,DM_CLASSID,1);
2071   for (p=&global->subdomainhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2072   ierr               = PetscMalloc(sizeof(struct _DMSubDomainHookLink),&link);CHKERRQ(ierr);
2073   link->restricthook = restricthook;
2074   link->ddhook       = ddhook;
2075   link->ctx          = ctx;
2076   link->next         = NULL;
2077   *p                 = link;
2078   PetscFunctionReturn(0);
2079 }
2080 
2081 #undef __FUNCT__
2082 #define __FUNCT__ "DMSubDomainRestrict"
2083 /*@
2084    DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd()
2085 
2086    Collective if any hooks are
2087 
2088    Input Arguments:
2089 +  fine - finer DM to use as a base
2090 .  oscatter - scatter from domain global vector filling subdomain global vector with overlap
2091 .  gscatter - scatter from domain global vector filling subdomain local vector with ghosts
2092 -  coarse - coarer DM to update
2093 
2094    Level: developer
2095 
2096 .seealso: DMCoarsenHookAdd(), MatRestrict()
2097 @*/
2098 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm)
2099 {
2100   PetscErrorCode      ierr;
2101   DMSubDomainHookLink link;
2102 
2103   PetscFunctionBegin;
2104   for (link=global->subdomainhook; link; link=link->next) {
2105     if (link->restricthook) {
2106       ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr);
2107     }
2108   }
2109   PetscFunctionReturn(0);
2110 }
2111 
2112 #undef __FUNCT__
2113 #define __FUNCT__ "DMGetCoarsenLevel"
2114 /*@
2115     DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM.
2116 
2117     Not Collective
2118 
2119     Input Parameter:
2120 .   dm - the DM object
2121 
2122     Output Parameter:
2123 .   level - number of coarsenings
2124 
2125     Level: developer
2126 
2127 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2128 
2129 @*/
2130 PetscErrorCode  DMGetCoarsenLevel(DM dm,PetscInt *level)
2131 {
2132   PetscFunctionBegin;
2133   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2134   *level = dm->leveldown;
2135   PetscFunctionReturn(0);
2136 }
2137 
2138 
2139 
2140 #undef __FUNCT__
2141 #define __FUNCT__ "DMRefineHierarchy"
2142 /*@C
2143     DMRefineHierarchy - Refines a DM object, all levels at once
2144 
2145     Collective on DM
2146 
2147     Input Parameter:
2148 +   dm - the DM object
2149 -   nlevels - the number of levels of refinement
2150 
2151     Output Parameter:
2152 .   dmf - the refined DM hierarchy
2153 
2154     Level: developer
2155 
2156 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2157 
2158 @*/
2159 PetscErrorCode  DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
2160 {
2161   PetscErrorCode ierr;
2162 
2163   PetscFunctionBegin;
2164   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2165   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2166   if (nlevels == 0) PetscFunctionReturn(0);
2167   if (dm->ops->refinehierarchy) {
2168     ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr);
2169   } else if (dm->ops->refine) {
2170     PetscInt i;
2171 
2172     ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr);
2173     for (i=1; i<nlevels; i++) {
2174       ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr);
2175     }
2176   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
2177   PetscFunctionReturn(0);
2178 }
2179 
2180 #undef __FUNCT__
2181 #define __FUNCT__ "DMCoarsenHierarchy"
2182 /*@C
2183     DMCoarsenHierarchy - Coarsens a DM object, all levels at once
2184 
2185     Collective on DM
2186 
2187     Input Parameter:
2188 +   dm - the DM object
2189 -   nlevels - the number of levels of coarsening
2190 
2191     Output Parameter:
2192 .   dmc - the coarsened DM hierarchy
2193 
2194     Level: developer
2195 
2196 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2197 
2198 @*/
2199 PetscErrorCode  DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
2200 {
2201   PetscErrorCode ierr;
2202 
2203   PetscFunctionBegin;
2204   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2205   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2206   if (nlevels == 0) PetscFunctionReturn(0);
2207   PetscValidPointer(dmc,3);
2208   if (dm->ops->coarsenhierarchy) {
2209     ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr);
2210   } else if (dm->ops->coarsen) {
2211     PetscInt i;
2212 
2213     ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr);
2214     for (i=1; i<nlevels; i++) {
2215       ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr);
2216     }
2217   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
2218   PetscFunctionReturn(0);
2219 }
2220 
2221 #undef __FUNCT__
2222 #define __FUNCT__ "DMCreateAggregates"
2223 /*@
2224    DMCreateAggregates - Gets the aggregates that map between
2225    grids associated with two DMs.
2226 
2227    Collective on DM
2228 
2229    Input Parameters:
2230 +  dmc - the coarse grid DM
2231 -  dmf - the fine grid DM
2232 
2233    Output Parameters:
2234 .  rest - the restriction matrix (transpose of the projection matrix)
2235 
2236    Level: intermediate
2237 
2238 .keywords: interpolation, restriction, multigrid
2239 
2240 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation()
2241 @*/
2242 PetscErrorCode  DMCreateAggregates(DM dmc, DM dmf, Mat *rest)
2243 {
2244   PetscErrorCode ierr;
2245 
2246   PetscFunctionBegin;
2247   PetscValidHeaderSpecific(dmc,DM_CLASSID,1);
2248   PetscValidHeaderSpecific(dmf,DM_CLASSID,2);
2249   ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr);
2250   PetscFunctionReturn(0);
2251 }
2252 
2253 #undef __FUNCT__
2254 #define __FUNCT__ "DMSetApplicationContextDestroy"
2255 /*@C
2256     DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed
2257 
2258     Not Collective
2259 
2260     Input Parameters:
2261 +   dm - the DM object
2262 -   destroy - the destroy function
2263 
2264     Level: intermediate
2265 
2266 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2267 
2268 @*/
2269 PetscErrorCode  DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**))
2270 {
2271   PetscFunctionBegin;
2272   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2273   dm->ctxdestroy = destroy;
2274   PetscFunctionReturn(0);
2275 }
2276 
2277 #undef __FUNCT__
2278 #define __FUNCT__ "DMSetApplicationContext"
2279 /*@
2280     DMSetApplicationContext - Set a user context into a DM object
2281 
2282     Not Collective
2283 
2284     Input Parameters:
2285 +   dm - the DM object
2286 -   ctx - the user context
2287 
2288     Level: intermediate
2289 
2290 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2291 
2292 @*/
2293 PetscErrorCode  DMSetApplicationContext(DM dm,void *ctx)
2294 {
2295   PetscFunctionBegin;
2296   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2297   dm->ctx = ctx;
2298   PetscFunctionReturn(0);
2299 }
2300 
2301 #undef __FUNCT__
2302 #define __FUNCT__ "DMGetApplicationContext"
2303 /*@
2304     DMGetApplicationContext - Gets a user context from a DM object
2305 
2306     Not Collective
2307 
2308     Input Parameter:
2309 .   dm - the DM object
2310 
2311     Output Parameter:
2312 .   ctx - the user context
2313 
2314     Level: intermediate
2315 
2316 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2317 
2318 @*/
2319 PetscErrorCode  DMGetApplicationContext(DM dm,void *ctx)
2320 {
2321   PetscFunctionBegin;
2322   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2323   *(void**)ctx = dm->ctx;
2324   PetscFunctionReturn(0);
2325 }
2326 
2327 #undef __FUNCT__
2328 #define __FUNCT__ "DMSetVariableBounds"
2329 /*@C
2330     DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI.
2331 
2332     Logically Collective on DM
2333 
2334     Input Parameter:
2335 +   dm - the DM object
2336 -   f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set)
2337 
2338     Level: intermediate
2339 
2340 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(),
2341          DMSetJacobian()
2342 
2343 @*/
2344 PetscErrorCode  DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
2345 {
2346   PetscFunctionBegin;
2347   dm->ops->computevariablebounds = f;
2348   PetscFunctionReturn(0);
2349 }
2350 
2351 #undef __FUNCT__
2352 #define __FUNCT__ "DMHasVariableBounds"
2353 /*@
2354     DMHasVariableBounds - does the DM object have a variable bounds function?
2355 
2356     Not Collective
2357 
2358     Input Parameter:
2359 .   dm - the DM object to destroy
2360 
2361     Output Parameter:
2362 .   flg - PETSC_TRUE if the variable bounds function exists
2363 
2364     Level: developer
2365 
2366 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2367 
2368 @*/
2369 PetscErrorCode  DMHasVariableBounds(DM dm,PetscBool  *flg)
2370 {
2371   PetscFunctionBegin;
2372   *flg =  (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
2373   PetscFunctionReturn(0);
2374 }
2375 
2376 #undef __FUNCT__
2377 #define __FUNCT__ "DMComputeVariableBounds"
2378 /*@C
2379     DMComputeVariableBounds - compute variable bounds used by SNESVI.
2380 
2381     Logically Collective on DM
2382 
2383     Input Parameters:
2384 +   dm - the DM object to destroy
2385 -   x  - current solution at which the bounds are computed
2386 
2387     Output parameters:
2388 +   xl - lower bound
2389 -   xu - upper bound
2390 
2391     Level: intermediate
2392 
2393 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2394 
2395 @*/
2396 PetscErrorCode  DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
2397 {
2398   PetscErrorCode ierr;
2399 
2400   PetscFunctionBegin;
2401   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
2402   PetscValidHeaderSpecific(xu,VEC_CLASSID,2);
2403   if (dm->ops->computevariablebounds) {
2404     ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr);
2405   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds.");
2406   PetscFunctionReturn(0);
2407 }
2408 
2409 #undef __FUNCT__
2410 #define __FUNCT__ "DMHasColoring"
2411 /*@
2412     DMHasColoring - does the DM object have a method of providing a coloring?
2413 
2414     Not Collective
2415 
2416     Input Parameter:
2417 .   dm - the DM object
2418 
2419     Output Parameter:
2420 .   flg - PETSC_TRUE if the DM has facilities for DMCreateColoring().
2421 
2422     Level: developer
2423 
2424 .seealso DMHasFunction(), DMCreateColoring()
2425 
2426 @*/
2427 PetscErrorCode  DMHasColoring(DM dm,PetscBool  *flg)
2428 {
2429   PetscFunctionBegin;
2430   *flg =  (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
2431   PetscFunctionReturn(0);
2432 }
2433 
2434 #undef  __FUNCT__
2435 #define __FUNCT__ "DMSetVec"
2436 /*@C
2437     DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear.
2438 
2439     Collective on DM
2440 
2441     Input Parameter:
2442 +   dm - the DM object
2443 -   x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems.
2444 
2445     Level: developer
2446 
2447 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2448 
2449 @*/
2450 PetscErrorCode  DMSetVec(DM dm,Vec x)
2451 {
2452   PetscErrorCode ierr;
2453 
2454   PetscFunctionBegin;
2455   if (x) {
2456     if (!dm->x) {
2457       ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr);
2458     }
2459     ierr = VecCopy(x,dm->x);CHKERRQ(ierr);
2460   } else if (dm->x) {
2461     ierr = VecDestroy(&dm->x);CHKERRQ(ierr);
2462   }
2463   PetscFunctionReturn(0);
2464 }
2465 
2466 PetscFunctionList DMList              = NULL;
2467 PetscBool         DMRegisterAllCalled = PETSC_FALSE;
2468 
2469 #undef __FUNCT__
2470 #define __FUNCT__ "DMSetType"
2471 /*@C
2472   DMSetType - Builds a DM, for a particular DM implementation.
2473 
2474   Collective on DM
2475 
2476   Input Parameters:
2477 + dm     - The DM object
2478 - method - The name of the DM type
2479 
2480   Options Database Key:
2481 . -dm_type <type> - Sets the DM type; use -help for a list of available types
2482 
2483   Notes:
2484   See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).
2485 
2486   Level: intermediate
2487 
2488 .keywords: DM, set, type
2489 .seealso: DMGetType(), DMCreate()
2490 @*/
2491 PetscErrorCode  DMSetType(DM dm, DMType method)
2492 {
2493   PetscErrorCode (*r)(DM);
2494   PetscBool      match;
2495   PetscErrorCode ierr;
2496 
2497   PetscFunctionBegin;
2498   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
2499   ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr);
2500   if (match) PetscFunctionReturn(0);
2501 
2502   if (!DMRegisterAllCalled) {ierr = DMRegisterAll();CHKERRQ(ierr);}
2503   ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr);
2504   if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
2505 
2506   if (dm->ops->destroy) {
2507     ierr             = (*dm->ops->destroy)(dm);CHKERRQ(ierr);
2508     dm->ops->destroy = NULL;
2509   }
2510   ierr = (*r)(dm);CHKERRQ(ierr);
2511   ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr);
2512   PetscFunctionReturn(0);
2513 }
2514 
2515 #undef __FUNCT__
2516 #define __FUNCT__ "DMGetType"
2517 /*@C
2518   DMGetType - Gets the DM type name (as a string) from the DM.
2519 
2520   Not Collective
2521 
2522   Input Parameter:
2523 . dm  - The DM
2524 
2525   Output Parameter:
2526 . type - The DM type name
2527 
2528   Level: intermediate
2529 
2530 .keywords: DM, get, type, name
2531 .seealso: DMSetType(), DMCreate()
2532 @*/
2533 PetscErrorCode  DMGetType(DM dm, DMType *type)
2534 {
2535   PetscErrorCode ierr;
2536 
2537   PetscFunctionBegin;
2538   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
2539   PetscValidPointer(type,2);
2540   if (!DMRegisterAllCalled) {
2541     ierr = DMRegisterAll();CHKERRQ(ierr);
2542   }
2543   *type = ((PetscObject)dm)->type_name;
2544   PetscFunctionReturn(0);
2545 }
2546 
2547 #undef __FUNCT__
2548 #define __FUNCT__ "DMConvert"
2549 /*@C
2550   DMConvert - Converts a DM to another DM, either of the same or different type.
2551 
2552   Collective on DM
2553 
2554   Input Parameters:
2555 + dm - the DM
2556 - newtype - new DM type (use "same" for the same type)
2557 
2558   Output Parameter:
2559 . M - pointer to new DM
2560 
2561   Notes:
2562   Cannot be used to convert a sequential DM to parallel or parallel to sequential,
2563   the MPI communicator of the generated DM is always the same as the communicator
2564   of the input DM.
2565 
2566   Level: intermediate
2567 
2568 .seealso: DMCreate()
2569 @*/
2570 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
2571 {
2572   DM             B;
2573   char           convname[256];
2574   PetscBool      sametype, issame;
2575   PetscErrorCode ierr;
2576 
2577   PetscFunctionBegin;
2578   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2579   PetscValidType(dm,1);
2580   PetscValidPointer(M,3);
2581   ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr);
2582   ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr);
2583   {
2584     PetscErrorCode (*conv)(DM, DMType, DM*) = NULL;
2585 
2586     /*
2587        Order of precedence:
2588        1) See if a specialized converter is known to the current DM.
2589        2) See if a specialized converter is known to the desired DM class.
2590        3) See if a good general converter is registered for the desired class
2591        4) See if a good general converter is known for the current matrix.
2592        5) Use a really basic converter.
2593     */
2594 
2595     /* 1) See if a specialized converter is known to the current DM and the desired class */
2596     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
2597     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
2598     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
2599     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
2600     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
2601     ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr);
2602     if (conv) goto foundconv;
2603 
2604     /* 2)  See if a specialized converter is known to the desired DM class. */
2605     ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr);
2606     ierr = DMSetType(B, newtype);CHKERRQ(ierr);
2607     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
2608     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
2609     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
2610     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
2611     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
2612     ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr);
2613     if (conv) {
2614       ierr = DMDestroy(&B);CHKERRQ(ierr);
2615       goto foundconv;
2616     }
2617 
2618 #if 0
2619     /* 3) See if a good general converter is registered for the desired class */
2620     conv = B->ops->convertfrom;
2621     ierr = DMDestroy(&B);CHKERRQ(ierr);
2622     if (conv) goto foundconv;
2623 
2624     /* 4) See if a good general converter is known for the current matrix */
2625     if (dm->ops->convert) {
2626       conv = dm->ops->convert;
2627     }
2628     if (conv) goto foundconv;
2629 #endif
2630 
2631     /* 5) Use a really basic converter. */
2632     SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);
2633 
2634 foundconv:
2635     ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
2636     ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr);
2637     ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
2638   }
2639   ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr);
2640   PetscFunctionReturn(0);
2641 }
2642 
2643 /*--------------------------------------------------------------------------------------------------------------------*/
2644 
2645 #undef __FUNCT__
2646 #define __FUNCT__ "DMRegister"
2647 /*@C
2648   DMRegister -  Adds a new DM component implementation
2649 
2650   Not Collective
2651 
2652   Input Parameters:
2653 + name        - The name of a new user-defined creation routine
2654 - create_func - The creation routine itself
2655 
2656   Notes:
2657   DMRegister() may be called multiple times to add several user-defined DMs
2658 
2659 
2660   Sample usage:
2661 .vb
2662     DMRegister("my_da", MyDMCreate);
2663 .ve
2664 
2665   Then, your DM type can be chosen with the procedural interface via
2666 .vb
2667     DMCreate(MPI_Comm, DM *);
2668     DMSetType(DM,"my_da");
2669 .ve
2670    or at runtime via the option
2671 .vb
2672     -da_type my_da
2673 .ve
2674 
2675   Level: advanced
2676 
2677 .keywords: DM, register
2678 .seealso: DMRegisterAll(), DMRegisterDestroy()
2679 
2680 @*/
2681 PetscErrorCode  DMRegister(const char sname[],PetscErrorCode (*function)(DM))
2682 {
2683   PetscErrorCode ierr;
2684 
2685   PetscFunctionBegin;
2686   ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr);
2687   PetscFunctionReturn(0);
2688 }
2689 
2690 #undef __FUNCT__
2691 #define __FUNCT__ "DMLoad"
2692 /*@C
2693   DMLoad - Loads a DM that has been stored in binary  with DMView().
2694 
2695   Collective on PetscViewer
2696 
2697   Input Parameters:
2698 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
2699            some related function before a call to DMLoad().
2700 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
2701            HDF5 file viewer, obtained from PetscViewerHDF5Open()
2702 
2703    Level: intermediate
2704 
2705   Notes:
2706    The type is determined by the data in the file, any type set into the DM before this call is ignored.
2707 
2708   Notes for advanced users:
2709   Most users should not need to know the details of the binary storage
2710   format, since DMLoad() and DMView() completely hide these details.
2711   But for anyone who's interested, the standard binary matrix storage
2712   format is
2713 .vb
2714      has not yet been determined
2715 .ve
2716 
2717 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad()
2718 @*/
2719 PetscErrorCode  DMLoad(DM newdm, PetscViewer viewer)
2720 {
2721   PetscBool      isbinary, ishdf5;
2722   PetscErrorCode ierr;
2723 
2724   PetscFunctionBegin;
2725   PetscValidHeaderSpecific(newdm,DM_CLASSID,1);
2726   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
2727   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
2728   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
2729   if (isbinary) {
2730     PetscInt classid;
2731     char     type[256];
2732 
2733     ierr = PetscViewerBinaryRead(viewer,&classid,1,PETSC_INT);CHKERRQ(ierr);
2734     if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid);
2735     ierr = PetscViewerBinaryRead(viewer,type,256,PETSC_CHAR);CHKERRQ(ierr);
2736     ierr = DMSetType(newdm, type);CHKERRQ(ierr);
2737     if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);}
2738   } else if (ishdf5) {
2739     if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);}
2740   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
2741   PetscFunctionReturn(0);
2742 }
2743 
2744 /******************************** FEM Support **********************************/
2745 
2746 #undef __FUNCT__
2747 #define __FUNCT__ "DMPrintCellVector"
2748 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
2749 {
2750   PetscInt       f;
2751   PetscErrorCode ierr;
2752 
2753   PetscFunctionBegin;
2754   ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
2755   for (f = 0; f < len; ++f) {
2756     ierr = PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr);
2757   }
2758   PetscFunctionReturn(0);
2759 }
2760 
2761 #undef __FUNCT__
2762 #define __FUNCT__ "DMPrintCellMatrix"
2763 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
2764 {
2765   PetscInt       f, g;
2766   PetscErrorCode ierr;
2767 
2768   PetscFunctionBegin;
2769   ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
2770   for (f = 0; f < rows; ++f) {
2771     ierr = PetscPrintf(PETSC_COMM_SELF, "  |");CHKERRQ(ierr);
2772     for (g = 0; g < cols; ++g) {
2773       ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr);
2774     }
2775     ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr);
2776   }
2777   PetscFunctionReturn(0);
2778 }
2779 
2780 #undef __FUNCT__
2781 #define __FUNCT__ "DMPrintLocalVec"
2782 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
2783 {
2784   PetscMPIInt    rank, numProcs;
2785   PetscInt       p;
2786   PetscErrorCode ierr;
2787 
2788   PetscFunctionBegin;
2789   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr);
2790   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr);
2791   ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "%s:\n", name);CHKERRQ(ierr);
2792   for (p = 0; p < numProcs; ++p) {
2793     if (p == rank) {
2794       Vec x;
2795 
2796       ierr = VecDuplicate(X, &x);CHKERRQ(ierr);
2797       ierr = VecCopy(X, x);CHKERRQ(ierr);
2798       ierr = VecChop(x, tol);CHKERRQ(ierr);
2799       ierr = VecView(x, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2800       ierr = VecDestroy(&x);CHKERRQ(ierr);
2801       ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2802     }
2803     ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr);
2804   }
2805   PetscFunctionReturn(0);
2806 }
2807 
2808 #undef __FUNCT__
2809 #define __FUNCT__ "DMGetDefaultSection"
2810 /*@
2811   DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM.
2812 
2813   Input Parameter:
2814 . dm - The DM
2815 
2816   Output Parameter:
2817 . section - The PetscSection
2818 
2819   Level: intermediate
2820 
2821   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
2822 
2823 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
2824 @*/
2825 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section)
2826 {
2827   PetscErrorCode ierr;
2828 
2829   PetscFunctionBegin;
2830   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2831   PetscValidPointer(section, 2);
2832   if (!dm->defaultSection && dm->ops->createdefaultsection) {ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr);}
2833   *section = dm->defaultSection;
2834   PetscFunctionReturn(0);
2835 }
2836 
2837 #undef __FUNCT__
2838 #define __FUNCT__ "DMSetDefaultSection"
2839 /*@
2840   DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM.
2841 
2842   Input Parameters:
2843 + dm - The DM
2844 - section - The PetscSection
2845 
2846   Level: intermediate
2847 
2848   Note: Any existing Section will be destroyed
2849 
2850 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
2851 @*/
2852 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section)
2853 {
2854   PetscInt       numFields;
2855   PetscInt       f;
2856   PetscErrorCode ierr;
2857 
2858   PetscFunctionBegin;
2859   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2860   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
2861   ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
2862   ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr);
2863   dm->defaultSection = section;
2864   ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);
2865   if (numFields) {
2866     ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr);
2867     for (f = 0; f < numFields; ++f) {
2868       PetscObject disc;
2869       const char *name;
2870 
2871       ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr);
2872       ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr);
2873       ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr);
2874     }
2875   }
2876   /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */
2877   ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr);
2878   PetscFunctionReturn(0);
2879 }
2880 
2881 #undef __FUNCT__
2882 #define __FUNCT__ "DMGetDefaultGlobalSection"
2883 /*@
2884   DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM.
2885 
2886   Collective on DM
2887 
2888   Input Parameter:
2889 . dm - The DM
2890 
2891   Output Parameter:
2892 . section - The PetscSection
2893 
2894   Level: intermediate
2895 
2896   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
2897 
2898 .seealso: DMSetDefaultSection(), DMGetDefaultSection()
2899 @*/
2900 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section)
2901 {
2902   PetscErrorCode ierr;
2903 
2904   PetscFunctionBegin;
2905   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2906   PetscValidPointer(section, 2);
2907   if (!dm->defaultGlobalSection) {
2908     PetscSection s;
2909 
2910     ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
2911     if (!s)  SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
2912     if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection");
2913     ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr);
2914     ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr);
2915     ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr);
2916   }
2917   *section = dm->defaultGlobalSection;
2918   PetscFunctionReturn(0);
2919 }
2920 
2921 #undef __FUNCT__
2922 #define __FUNCT__ "DMSetDefaultGlobalSection"
2923 /*@
2924   DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM.
2925 
2926   Input Parameters:
2927 + dm - The DM
2928 - section - The PetscSection, or NULL
2929 
2930   Level: intermediate
2931 
2932   Note: Any existing Section will be destroyed
2933 
2934 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection()
2935 @*/
2936 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section)
2937 {
2938   PetscErrorCode ierr;
2939 
2940   PetscFunctionBegin;
2941   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2942   if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
2943   ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
2944   ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr);
2945   dm->defaultGlobalSection = section;
2946   PetscFunctionReturn(0);
2947 }
2948 
2949 #undef __FUNCT__
2950 #define __FUNCT__ "DMGetDefaultSF"
2951 /*@
2952   DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set,
2953   it is created from the default PetscSection layouts in the DM.
2954 
2955   Input Parameter:
2956 . dm - The DM
2957 
2958   Output Parameter:
2959 . sf - The PetscSF
2960 
2961   Level: intermediate
2962 
2963   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
2964 
2965 .seealso: DMSetDefaultSF(), DMCreateDefaultSF()
2966 @*/
2967 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf)
2968 {
2969   PetscInt       nroots;
2970   PetscErrorCode ierr;
2971 
2972   PetscFunctionBegin;
2973   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2974   PetscValidPointer(sf, 2);
2975   ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
2976   if (nroots < 0) {
2977     PetscSection section, gSection;
2978 
2979     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
2980     if (section) {
2981       ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr);
2982       ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr);
2983     } else {
2984       *sf = NULL;
2985       PetscFunctionReturn(0);
2986     }
2987   }
2988   *sf = dm->defaultSF;
2989   PetscFunctionReturn(0);
2990 }
2991 
2992 #undef __FUNCT__
2993 #define __FUNCT__ "DMSetDefaultSF"
2994 /*@
2995   DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM
2996 
2997   Input Parameters:
2998 + dm - The DM
2999 - sf - The PetscSF
3000 
3001   Level: intermediate
3002 
3003   Note: Any previous SF is destroyed
3004 
3005 .seealso: DMGetDefaultSF(), DMCreateDefaultSF()
3006 @*/
3007 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf)
3008 {
3009   PetscErrorCode ierr;
3010 
3011   PetscFunctionBegin;
3012   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3013   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
3014   ierr          = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr);
3015   dm->defaultSF = sf;
3016   PetscFunctionReturn(0);
3017 }
3018 
3019 #undef __FUNCT__
3020 #define __FUNCT__ "DMCreateDefaultSF"
3021 /*@C
3022   DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections
3023   describing the data layout.
3024 
3025   Input Parameters:
3026 + dm - The DM
3027 . localSection - PetscSection describing the local data layout
3028 - globalSection - PetscSection describing the global data layout
3029 
3030   Level: intermediate
3031 
3032 .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3033 @*/
3034 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection)
3035 {
3036   MPI_Comm       comm;
3037   PetscLayout    layout;
3038   const PetscInt *ranges;
3039   PetscInt       *local;
3040   PetscSFNode    *remote;
3041   PetscInt       pStart, pEnd, p, nroots, nleaves = 0, l;
3042   PetscMPIInt    size, rank;
3043   PetscErrorCode ierr;
3044 
3045   PetscFunctionBegin;
3046   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
3047   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3048   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
3049   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3050   ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr);
3051   ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr);
3052   ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
3053   ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
3054   ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr);
3055   ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
3056   ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
3057   for (p = pStart; p < pEnd; ++p) {
3058     PetscInt gdof, gcdof;
3059 
3060     ierr     = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3061     ierr     = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3062     if (gcdof > (gdof < 0 ? -(gdof+1) : gdof)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d has %d constraints > %d dof", p, gcdof, (gdof < 0 ? -(gdof+1) : gdof));
3063     nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3064   }
3065   ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr);
3066   ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr);
3067   for (p = pStart, l = 0; p < pEnd; ++p) {
3068     const PetscInt *cind;
3069     PetscInt       dof, cdof, off, gdof, gcdof, goff, gsize, d, c;
3070 
3071     ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr);
3072     ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr);
3073     ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr);
3074     ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr);
3075     ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3076     ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3077     ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr);
3078     if (!gdof) continue; /* Censored point */
3079     gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3080     if (gsize != dof-cdof) {
3081       if (gsize != dof) SETERRQ4(comm, PETSC_ERR_ARG_WRONG, "Global dof %d for point %d is neither the constrained size %d, nor the unconstrained %d", gsize, p, dof-cdof, dof);
3082       cdof = 0; /* Ignore constraints */
3083     }
3084     for (d = 0, c = 0; d < dof; ++d) {
3085       if ((c < cdof) && (cind[c] == d)) {++c; continue;}
3086       local[l+d-c] = off+d;
3087     }
3088     if (gdof < 0) {
3089       for (d = 0; d < gsize; ++d, ++l) {
3090         PetscInt offset = -(goff+1) + d, r;
3091 
3092         ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr);
3093         if (r < 0) r = -(r+2);
3094         if ((r < 0) || (r >= size)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d mapped to invalid process %d (%d, %d)", p, r, gdof, goff);
3095         remote[l].rank  = r;
3096         remote[l].index = offset - ranges[r];
3097       }
3098     } else {
3099       for (d = 0; d < gsize; ++d, ++l) {
3100         remote[l].rank  = rank;
3101         remote[l].index = goff+d - ranges[rank];
3102       }
3103     }
3104   }
3105   if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves);
3106   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
3107   ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr);
3108   PetscFunctionReturn(0);
3109 }
3110 
3111 #undef __FUNCT__
3112 #define __FUNCT__ "DMGetPointSF"
3113 /*@
3114   DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM.
3115 
3116   Input Parameter:
3117 . dm - The DM
3118 
3119   Output Parameter:
3120 . sf - The PetscSF
3121 
3122   Level: intermediate
3123 
3124   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3125 
3126 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3127 @*/
3128 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
3129 {
3130   PetscFunctionBegin;
3131   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3132   PetscValidPointer(sf, 2);
3133   *sf = dm->sf;
3134   PetscFunctionReturn(0);
3135 }
3136 
3137 #undef __FUNCT__
3138 #define __FUNCT__ "DMSetPointSF"
3139 /*@
3140   DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM.
3141 
3142   Input Parameters:
3143 + dm - The DM
3144 - sf - The PetscSF
3145 
3146   Level: intermediate
3147 
3148 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3149 @*/
3150 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
3151 {
3152   PetscErrorCode ierr;
3153 
3154   PetscFunctionBegin;
3155   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3156   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
3157   ierr   = PetscSFDestroy(&dm->sf);CHKERRQ(ierr);
3158   ierr   = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr);
3159   dm->sf = sf;
3160   PetscFunctionReturn(0);
3161 }
3162 
3163 #undef __FUNCT__
3164 #define __FUNCT__ "DMGetDS"
3165 /*@
3166   DMGetDS - Get the PetscDS
3167 
3168   Input Parameter:
3169 . dm - The DM
3170 
3171   Output Parameter:
3172 . prob - The PetscDS
3173 
3174   Level: developer
3175 
3176 .seealso: DMSetDS()
3177 @*/
3178 PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
3179 {
3180   PetscFunctionBegin;
3181   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3182   PetscValidPointer(prob, 2);
3183   *prob = dm->prob;
3184   PetscFunctionReturn(0);
3185 }
3186 
3187 #undef __FUNCT__
3188 #define __FUNCT__ "DMSetDS"
3189 /*@
3190   DMSetDS - Set the PetscDS
3191 
3192   Input Parameters:
3193 + dm - The DM
3194 - prob - The PetscDS
3195 
3196   Level: developer
3197 
3198 .seealso: DMGetDS()
3199 @*/
3200 PetscErrorCode DMSetDS(DM dm, PetscDS prob)
3201 {
3202   PetscErrorCode ierr;
3203 
3204   PetscFunctionBegin;
3205   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3206   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2);
3207   ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr);
3208   dm->prob = prob;
3209   ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr);
3210   PetscFunctionReturn(0);
3211 }
3212 
3213 #undef __FUNCT__
3214 #define __FUNCT__ "DMGetNumFields"
3215 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
3216 {
3217   PetscErrorCode ierr;
3218 
3219   PetscFunctionBegin;
3220   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3221   ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr);
3222   PetscFunctionReturn(0);
3223 }
3224 
3225 #undef __FUNCT__
3226 #define __FUNCT__ "DMSetNumFields"
3227 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
3228 {
3229   PetscInt       Nf, f;
3230   PetscErrorCode ierr;
3231 
3232   PetscFunctionBegin;
3233   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3234   ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr);
3235   for (f = Nf; f < numFields; ++f) {
3236     PetscContainer obj;
3237 
3238     ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr);
3239     ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr);
3240     ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr);
3241   }
3242   PetscFunctionReturn(0);
3243 }
3244 
3245 #undef __FUNCT__
3246 #define __FUNCT__ "DMGetField"
3247 /*@
3248   DMGetField - Return the discretization object for a given DM field
3249 
3250   Not collective
3251 
3252   Input Parameters:
3253 + dm - The DM
3254 - f  - The field number
3255 
3256   Output Parameter:
3257 . field - The discretization object
3258 
3259   Level: developer
3260 
3261 .seealso: DMSetField()
3262 @*/
3263 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field)
3264 {
3265   PetscErrorCode ierr;
3266 
3267   PetscFunctionBegin;
3268   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3269   ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr);
3270   PetscFunctionReturn(0);
3271 }
3272 
3273 #undef __FUNCT__
3274 #define __FUNCT__ "DMSetField"
3275 /*@
3276   DMSetField - Set the discretization object for a given DM field
3277 
3278   Logically collective on DM
3279 
3280   Input Parameters:
3281 + dm - The DM
3282 . f  - The field number
3283 - field - The discretization object
3284 
3285   Level: developer
3286 
3287 .seealso: DMGetField()
3288 @*/
3289 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field)
3290 {
3291   PetscErrorCode ierr;
3292 
3293   PetscFunctionBegin;
3294   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3295   ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr);
3296   PetscFunctionReturn(0);
3297 }
3298 
3299 #undef __FUNCT__
3300 #define __FUNCT__ "DMRestrictHook_Coordinates"
3301 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx)
3302 {
3303   DM dm_coord,dmc_coord;
3304   PetscErrorCode ierr;
3305   Vec coords,ccoords;
3306   VecScatter scat;
3307   PetscFunctionBegin;
3308   ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr);
3309   ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr);
3310   ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
3311   ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr);
3312   if (coords && !ccoords) {
3313     ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr);
3314     ierr = DMCreateInjection(dmc_coord,dm_coord,&scat);CHKERRQ(ierr);
3315     ierr = VecScatterBegin(scat,coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3316     ierr = VecScatterEnd(scat,coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3317     ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr);
3318     ierr = VecScatterDestroy(&scat);CHKERRQ(ierr);
3319     ierr = VecDestroy(&ccoords);CHKERRQ(ierr);
3320   }
3321   PetscFunctionReturn(0);
3322 }
3323 
3324 #undef __FUNCT__
3325 #define __FUNCT__ "DMSubDomainHook_Coordinates"
3326 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx)
3327 {
3328   DM dm_coord,subdm_coord;
3329   PetscErrorCode ierr;
3330   Vec coords,ccoords,clcoords;
3331   VecScatter *scat_i,*scat_g;
3332   PetscFunctionBegin;
3333   ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr);
3334   ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr);
3335   ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
3336   ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr);
3337   if (coords && !ccoords) {
3338     ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr);
3339     ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr);
3340     ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr);
3341     ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3342     ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3343     ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3344     ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3345     ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr);
3346     ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr);
3347     ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr);
3348     ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr);
3349     ierr = VecDestroy(&ccoords);CHKERRQ(ierr);
3350     ierr = VecDestroy(&clcoords);CHKERRQ(ierr);
3351     ierr = PetscFree(scat_i);CHKERRQ(ierr);
3352     ierr = PetscFree(scat_g);CHKERRQ(ierr);
3353   }
3354   PetscFunctionReturn(0);
3355 }
3356 
3357 #undef __FUNCT__
3358 #define __FUNCT__ "DMGetDimension"
3359 /*@
3360   DMGetDimension - Return the topological dimension of the DM
3361 
3362   Not collective
3363 
3364   Input Parameter:
3365 . dm - The DM
3366 
3367   Output Parameter:
3368 . dim - The topological dimension
3369 
3370   Level: beginner
3371 
3372 .seealso: DMSetDimension(), DMCreate()
3373 @*/
3374 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
3375 {
3376   PetscFunctionBegin;
3377   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3378   PetscValidPointer(dim, 2);
3379   *dim = dm->dim;
3380   PetscFunctionReturn(0);
3381 }
3382 
3383 #undef __FUNCT__
3384 #define __FUNCT__ "DMSetDimension"
3385 /*@
3386   DMSetDimension - Set the topological dimension of the DM
3387 
3388   Collective on dm
3389 
3390   Input Parameters:
3391 + dm - The DM
3392 - dim - The topological dimension
3393 
3394   Level: beginner
3395 
3396 .seealso: DMGetDimension(), DMCreate()
3397 @*/
3398 PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
3399 {
3400   PetscFunctionBegin;
3401   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3402   PetscValidLogicalCollectiveInt(dm, dim, 2);
3403   dm->dim = dim;
3404   PetscFunctionReturn(0);
3405 }
3406 
3407 #undef __FUNCT__
3408 #define __FUNCT__ "DMGetDimPoints"
3409 /*@
3410   DMGetDimPoints - Get the half-open interval for all points of a given dimension
3411 
3412   Collective on DM
3413 
3414   Input Parameters:
3415 + dm - the DM
3416 - dim - the dimension
3417 
3418   Output Parameters:
3419 + pStart - The first point of the given dimension
3420 . pEnd - The first point following points of the given dimension
3421 
3422   Note:
3423   The points are vertices in the Hasse diagram encoding the topology. This is explained in
3424   http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme,
3425   then the interval is empty.
3426 
3427   Level: intermediate
3428 
3429 .keywords: point, Hasse Diagram, dimension
3430 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum()
3431 @*/
3432 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
3433 {
3434   PetscInt       d;
3435   PetscErrorCode ierr;
3436 
3437   PetscFunctionBegin;
3438   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3439   ierr = DMGetDimension(dm, &d);CHKERRQ(ierr);
3440   if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d);
3441   ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr);
3442   PetscFunctionReturn(0);
3443 }
3444 
3445 #undef __FUNCT__
3446 #define __FUNCT__ "DMSetCoordinates"
3447 /*@
3448   DMSetCoordinates - Sets into the DM a global vector that holds the coordinates
3449 
3450   Collective on DM
3451 
3452   Input Parameters:
3453 + dm - the DM
3454 - c - coordinate vector
3455 
3456   Note:
3457   The coordinates do include those for ghost points, which are in the local vector
3458 
3459   Level: intermediate
3460 
3461 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3462 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM()
3463 @*/
3464 PetscErrorCode DMSetCoordinates(DM dm, Vec c)
3465 {
3466   PetscErrorCode ierr;
3467 
3468   PetscFunctionBegin;
3469   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3470   PetscValidHeaderSpecific(c,VEC_CLASSID,2);
3471   ierr            = PetscObjectReference((PetscObject) c);CHKERRQ(ierr);
3472   ierr            = VecDestroy(&dm->coordinates);CHKERRQ(ierr);
3473   dm->coordinates = c;
3474   ierr            = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr);
3475   ierr            = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr);
3476   ierr            = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr);
3477   PetscFunctionReturn(0);
3478 }
3479 
3480 #undef __FUNCT__
3481 #define __FUNCT__ "DMSetCoordinatesLocal"
3482 /*@
3483   DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates
3484 
3485   Collective on DM
3486 
3487    Input Parameters:
3488 +  dm - the DM
3489 -  c - coordinate vector
3490 
3491   Note:
3492   The coordinates of ghost points can be set using DMSetCoordinates()
3493   followed by DMGetCoordinatesLocal(). This is intended to enable the
3494   setting of ghost coordinates outside of the domain.
3495 
3496   Level: intermediate
3497 
3498 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3499 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM()
3500 @*/
3501 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c)
3502 {
3503   PetscErrorCode ierr;
3504 
3505   PetscFunctionBegin;
3506   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3507   PetscValidHeaderSpecific(c,VEC_CLASSID,2);
3508   ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr);
3509   ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr);
3510 
3511   dm->coordinatesLocal = c;
3512 
3513   ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr);
3514   PetscFunctionReturn(0);
3515 }
3516 
3517 #undef __FUNCT__
3518 #define __FUNCT__ "DMGetCoordinates"
3519 /*@
3520   DMGetCoordinates - Gets a global vector with the coordinates associated with the DM.
3521 
3522   Not Collective
3523 
3524   Input Parameter:
3525 . dm - the DM
3526 
3527   Output Parameter:
3528 . c - global coordinate vector
3529 
3530   Note:
3531   This is a borrowed reference, so the user should NOT destroy this vector
3532 
3533   Each process has only the local coordinates (does NOT have the ghost coordinates).
3534 
3535   For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
3536   and (x_0,y_0,z_0,x_1,y_1,z_1...)
3537 
3538   Level: intermediate
3539 
3540 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3541 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
3542 @*/
3543 PetscErrorCode DMGetCoordinates(DM dm, Vec *c)
3544 {
3545   PetscErrorCode ierr;
3546 
3547   PetscFunctionBegin;
3548   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3549   PetscValidPointer(c,2);
3550   if (!dm->coordinates && dm->coordinatesLocal) {
3551     DM cdm = NULL;
3552 
3553     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
3554     ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr);
3555     ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr);
3556     ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr);
3557     ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr);
3558   }
3559   *c = dm->coordinates;
3560   PetscFunctionReturn(0);
3561 }
3562 
3563 #undef __FUNCT__
3564 #define __FUNCT__ "DMGetCoordinatesLocal"
3565 /*@
3566   DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM.
3567 
3568   Collective on DM
3569 
3570   Input Parameter:
3571 . dm - the DM
3572 
3573   Output Parameter:
3574 . c - coordinate vector
3575 
3576   Note:
3577   This is a borrowed reference, so the user should NOT destroy this vector
3578 
3579   Each process has the local and ghost coordinates
3580 
3581   For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
3582   and (x_0,y_0,z_0,x_1,y_1,z_1...)
3583 
3584   Level: intermediate
3585 
3586 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3587 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM()
3588 @*/
3589 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c)
3590 {
3591   PetscErrorCode ierr;
3592 
3593   PetscFunctionBegin;
3594   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3595   PetscValidPointer(c,2);
3596   if (!dm->coordinatesLocal && dm->coordinates) {
3597     DM cdm = NULL;
3598 
3599     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
3600     ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr);
3601     ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr);
3602     ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr);
3603     ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr);
3604   }
3605   *c = dm->coordinatesLocal;
3606   PetscFunctionReturn(0);
3607 }
3608 
3609 #undef __FUNCT__
3610 #define __FUNCT__ "DMGetCoordinateDM"
3611 /*@
3612   DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates
3613 
3614   Collective on DM
3615 
3616   Input Parameter:
3617 . dm - the DM
3618 
3619   Output Parameter:
3620 . cdm - coordinate DM
3621 
3622   Level: intermediate
3623 
3624 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3625 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
3626 @*/
3627 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm)
3628 {
3629   PetscErrorCode ierr;
3630 
3631   PetscFunctionBegin;
3632   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3633   PetscValidPointer(cdm,2);
3634   if (!dm->coordinateDM) {
3635     if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM");
3636     ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr);
3637   }
3638   *cdm = dm->coordinateDM;
3639   PetscFunctionReturn(0);
3640 }
3641 
3642 #undef __FUNCT__
3643 #define __FUNCT__ "DMSetCoordinateDM"
3644 /*@
3645   DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates
3646 
3647   Logically Collective on DM
3648 
3649   Input Parameters:
3650 + dm - the DM
3651 - cdm - coordinate DM
3652 
3653   Level: intermediate
3654 
3655 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3656 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
3657 @*/
3658 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm)
3659 {
3660   PetscErrorCode ierr;
3661 
3662   PetscFunctionBegin;
3663   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3664   PetscValidHeaderSpecific(cdm,DM_CLASSID,2);
3665   ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr);
3666   dm->coordinateDM = cdm;
3667   ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr);
3668   PetscFunctionReturn(0);
3669 }
3670 
3671 #undef __FUNCT__
3672 #define __FUNCT__ "DMGetCoordinateDim"
3673 /*@
3674   DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values.
3675 
3676   Not Collective
3677 
3678   Input Parameter:
3679 . dm - The DM object
3680 
3681   Output Parameter:
3682 . dim - The embedding dimension
3683 
3684   Level: intermediate
3685 
3686 .keywords: mesh, coordinates
3687 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
3688 @*/
3689 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim)
3690 {
3691   PetscFunctionBegin;
3692   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3693   PetscValidPointer(dim, 2);
3694   *dim = dm->dimEmbed;
3695   PetscFunctionReturn(0);
3696 }
3697 
3698 #undef __FUNCT__
3699 #define __FUNCT__ "DMSetCoordinateDim"
3700 /*@
3701   DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values.
3702 
3703   Not Collective
3704 
3705   Input Parameters:
3706 + dm  - The DM object
3707 - dim - The embedding dimension
3708 
3709   Level: intermediate
3710 
3711 .keywords: mesh, coordinates
3712 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
3713 @*/
3714 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim)
3715 {
3716   PetscFunctionBegin;
3717   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3718   dm->dimEmbed = dim;
3719   PetscFunctionReturn(0);
3720 }
3721 
3722 #undef __FUNCT__
3723 #define __FUNCT__ "DMGetCoordinateSection"
3724 /*@
3725   DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh.
3726 
3727   Not Collective
3728 
3729   Input Parameter:
3730 . dm - The DM object
3731 
3732   Output Parameter:
3733 . section - The PetscSection object
3734 
3735   Level: intermediate
3736 
3737 .keywords: mesh, coordinates
3738 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
3739 @*/
3740 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section)
3741 {
3742   DM             cdm;
3743   PetscErrorCode ierr;
3744 
3745   PetscFunctionBegin;
3746   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3747   PetscValidPointer(section, 2);
3748   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
3749   ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr);
3750   PetscFunctionReturn(0);
3751 }
3752 
3753 #undef __FUNCT__
3754 #define __FUNCT__ "DMSetCoordinateSection"
3755 /*@
3756   DMSetCoordinateSection - Set the layout of coordinate values over the mesh.
3757 
3758   Not Collective
3759 
3760   Input Parameters:
3761 + dm      - The DM object
3762 . dim     - The embedding dimension, or PETSC_DETERMINE
3763 - section - The PetscSection object
3764 
3765   Level: intermediate
3766 
3767 .keywords: mesh, coordinates
3768 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
3769 @*/
3770 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section)
3771 {
3772   DM             cdm;
3773   PetscErrorCode ierr;
3774 
3775   PetscFunctionBegin;
3776   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3777   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3);
3778   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
3779   ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr);
3780   if (dim == PETSC_DETERMINE) {
3781     PetscInt d = dim;
3782     PetscInt pStart, pEnd, vStart, vEnd, v, dd;
3783 
3784     ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
3785     ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
3786     pStart = PetscMax(vStart, pStart);
3787     pEnd   = PetscMin(vEnd, pEnd);
3788     for (v = pStart; v < pEnd; ++v) {
3789       ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr);
3790       if (dd) {d = dd; break;}
3791     }
3792     ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);
3793   }
3794   PetscFunctionReturn(0);
3795 }
3796 
3797 #undef __FUNCT__
3798 #define __FUNCT__ "DMGetPeriodicity"
3799 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L)
3800 {
3801   PetscFunctionBegin;
3802   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3803   if (L)       *L       = dm->L;
3804   if (maxCell) *maxCell = dm->maxCell;
3805   PetscFunctionReturn(0);
3806 }
3807 
3808 #undef __FUNCT__
3809 #define __FUNCT__ "DMSetPeriodicity"
3810 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[])
3811 {
3812   Vec            coordinates;
3813   PetscInt       dim, d;
3814   PetscErrorCode ierr;
3815 
3816   PetscFunctionBegin;
3817   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3818   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
3819   ierr = VecGetBlockSize(coordinates, &dim);CHKERRQ(ierr);
3820   ierr = PetscMalloc1(dim,&dm->L);CHKERRQ(ierr);
3821   ierr = PetscMalloc1(dim,&dm->maxCell);CHKERRQ(ierr);
3822   for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d];}
3823   PetscFunctionReturn(0);
3824 }
3825 
3826 #undef __FUNCT__
3827 #define __FUNCT__ "DMLocatePoints"
3828 /*@
3829   DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells
3830 
3831   Not collective
3832 
3833   Input Parameters:
3834 + dm - The DM
3835 - v - The Vec of points
3836 
3837   Output Parameter:
3838 . cells - The local cell numbers for cells which contain the points
3839 
3840   Level: developer
3841 
3842 .keywords: point location, mesh
3843 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
3844 @*/
3845 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells)
3846 {
3847   PetscErrorCode ierr;
3848 
3849   PetscFunctionBegin;
3850   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3851   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
3852   PetscValidPointer(cells,3);
3853   if (dm->ops->locatepoints) {
3854     ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr);
3855   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM");
3856   PetscFunctionReturn(0);
3857 }
3858 
3859 #undef __FUNCT__
3860 #define __FUNCT__ "DMGetOutputDM"
3861 /*@
3862   DMGetOutputDM - Retrieve the DM associated with the layout for output
3863 
3864   Input Parameter:
3865 . dm - The original DM
3866 
3867   Output Parameter:
3868 . odm - The DM which provides the layout for output
3869 
3870   Level: intermediate
3871 
3872 .seealso: VecView(), DMGetDefaultGlobalSection()
3873 @*/
3874 PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
3875 {
3876   PetscSection   section;
3877   PetscBool      hasConstraints;
3878   PetscErrorCode ierr;
3879 
3880   PetscFunctionBegin;
3881   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3882   PetscValidPointer(odm,2);
3883   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
3884   ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr);
3885   if (!hasConstraints) {
3886     *odm = dm;
3887     PetscFunctionReturn(0);
3888   }
3889   if (!dm->dmBC) {
3890     PetscSection newSection, gsection;
3891     PetscSF      sf;
3892 
3893     ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr);
3894     ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr);
3895     ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr);
3896     ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr);
3897     ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr);
3898     ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, &gsection);CHKERRQ(ierr);
3899     ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr);
3900     ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr);
3901   }
3902   *odm = dm->dmBC;
3903   PetscFunctionReturn(0);
3904 }
3905 
3906 #undef __FUNCT__
3907 #define __FUNCT__ "DMGetOutputSequenceNumber"
3908 /*@
3909   DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
3910 
3911   Input Parameter:
3912 . dm - The original DM
3913 
3914   Output Parameters:
3915 + num - The output sequence number
3916 - val - The output sequence value
3917 
3918   Level: intermediate
3919 
3920   Note: This is intended for output that should appear in sequence, for instance
3921   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
3922 
3923 .seealso: VecView()
3924 @*/
3925 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
3926 {
3927   PetscFunctionBegin;
3928   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3929   if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;}
3930   if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;}
3931   PetscFunctionReturn(0);
3932 }
3933 
3934 #undef __FUNCT__
3935 #define __FUNCT__ "DMSetOutputSequenceNumber"
3936 /*@
3937   DMSetOutputSequenceNumber - Set the sequence number/value for output
3938 
3939   Input Parameters:
3940 + dm - The original DM
3941 . num - The output sequence number
3942 - val - The output sequence value
3943 
3944   Level: intermediate
3945 
3946   Note: This is intended for output that should appear in sequence, for instance
3947   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
3948 
3949 .seealso: VecView()
3950 @*/
3951 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
3952 {
3953   PetscFunctionBegin;
3954   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3955   dm->outputSequenceNum = num;
3956   dm->outputSequenceVal = val;
3957   PetscFunctionReturn(0);
3958 }
3959 
3960 #undef __FUNCT__
3961 #define __FUNCT__ "DMOutputSequenceLoad"
3962 /*@C
3963   DMOutputSequenceLoad - Retrieve the sequence value from a Viewer
3964 
3965   Input Parameters:
3966 + dm   - The original DM
3967 . name - The sequence name
3968 - num  - The output sequence number
3969 
3970   Output Parameter:
3971 . val  - The output sequence value
3972 
3973   Level: intermediate
3974 
3975   Note: This is intended for output that should appear in sequence, for instance
3976   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
3977 
3978 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView()
3979 @*/
3980 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
3981 {
3982   PetscBool      ishdf5;
3983   PetscErrorCode ierr;
3984 
3985   PetscFunctionBegin;
3986   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3987   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
3988   PetscValidPointer(val,4);
3989   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
3990   if (ishdf5) {
3991 #if defined(PETSC_HAVE_HDF5)
3992     PetscScalar value;
3993 
3994     ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr);
3995     *val = PetscRealPart(value);
3996 #endif
3997   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
3998   PetscFunctionReturn(0);
3999 }
4000