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