xref: /petsc/src/dm/interface/dm.c (revision 76f543a4c4f87cb621fd5325ef6ac5a2003d4fa9)
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 base point.
1722 -   g - the global vector
1723 
1724     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
1725            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
1726            global array to the final global array with VecAXPY().
1727 
1728     Level: beginner
1729 
1730 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()
1731 
1732 @*/
1733 PetscErrorCode  DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
1734 {
1735   PetscSF        sf;
1736   PetscErrorCode ierr;
1737 
1738   PetscFunctionBegin;
1739   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1740   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1741   if (sf) {
1742     MPI_Op      op;
1743     PetscScalar *lArray, *gArray;
1744 
1745     switch (mode) {
1746     case INSERT_VALUES:
1747     case INSERT_ALL_VALUES:
1748       op = MPIU_REPLACE; break;
1749     case ADD_VALUES:
1750     case ADD_ALL_VALUES:
1751       op = MPI_SUM; break;
1752     default:
1753       SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1754     }
1755     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1756     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
1757     ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, op);CHKERRQ(ierr);
1758     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1759     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
1760   } else {
1761     ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr);
1762   }
1763   PetscFunctionReturn(0);
1764 }
1765 
1766 #undef __FUNCT__
1767 #define __FUNCT__ "DMLocalToGlobalEnd"
1768 /*@
1769     DMLocalToGlobalEnd - updates global vectors from local vectors
1770 
1771     Neighbor-wise Collective on DM
1772 
1773     Input Parameters:
1774 +   dm - the DM object
1775 .   l - the local vector
1776 .   mode - INSERT_VALUES or ADD_VALUES
1777 -   g - the global vector
1778 
1779 
1780     Level: beginner
1781 
1782 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()
1783 
1784 @*/
1785 PetscErrorCode  DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
1786 {
1787   PetscSF        sf;
1788   PetscErrorCode ierr;
1789 
1790   PetscFunctionBegin;
1791   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1792   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1793   if (sf) {
1794     MPI_Op      op;
1795     PetscScalar *lArray, *gArray;
1796 
1797     switch (mode) {
1798     case INSERT_VALUES:
1799     case INSERT_ALL_VALUES:
1800       op = MPIU_REPLACE; break;
1801     case ADD_VALUES:
1802     case ADD_ALL_VALUES:
1803       op = MPI_SUM; break;
1804     default:
1805       SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1806     }
1807     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1808     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
1809     ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, op);CHKERRQ(ierr);
1810     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1811     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
1812   } else {
1813     ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr);
1814   }
1815   PetscFunctionReturn(0);
1816 }
1817 
1818 #undef __FUNCT__
1819 #define __FUNCT__ "DMLocalToLocalBegin"
1820 /*@
1821    DMLocalToLocalBegin - Maps from a local vector (including ghost points
1822    that contain irrelevant values) to another local vector where the ghost
1823    points in the second are set correctly. Must be followed by DMLocalToLocalEnd().
1824 
1825    Neighbor-wise Collective on DM and Vec
1826 
1827    Input Parameters:
1828 +  dm - the DM object
1829 .  g - the original local vector
1830 -  mode - one of INSERT_VALUES or ADD_VALUES
1831 
1832    Output Parameter:
1833 .  l  - the local vector with correct ghost values
1834 
1835    Level: intermediate
1836 
1837    Notes:
1838    The local vectors used here need not be the same as those
1839    obtained from DMCreateLocalVector(), BUT they
1840    must have the same parallel data layout; they could, for example, be
1841    obtained with VecDuplicate() from the DM originating vectors.
1842 
1843 .keywords: DM, local-to-local, begin
1844 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
1845 
1846 @*/
1847 PetscErrorCode  DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
1848 {
1849   PetscErrorCode          ierr;
1850 
1851   PetscFunctionBegin;
1852   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1853   ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
1854   PetscFunctionReturn(0);
1855 }
1856 
1857 #undef __FUNCT__
1858 #define __FUNCT__ "DMLocalToLocalEnd"
1859 /*@
1860    DMLocalToLocalEnd - Maps from a local vector (including ghost points
1861    that contain irrelevant values) to another local vector where the ghost
1862    points in the second are set correctly. Must be preceded by DMLocalToLocalBegin().
1863 
1864    Neighbor-wise Collective on DM and Vec
1865 
1866    Input Parameters:
1867 +  da - the DM object
1868 .  g - the original local vector
1869 -  mode - one of INSERT_VALUES or ADD_VALUES
1870 
1871    Output Parameter:
1872 .  l  - the local vector with correct ghost values
1873 
1874    Level: intermediate
1875 
1876    Notes:
1877    The local vectors used here need not be the same as those
1878    obtained from DMCreateLocalVector(), BUT they
1879    must have the same parallel data layout; they could, for example, be
1880    obtained with VecDuplicate() from the DM originating vectors.
1881 
1882 .keywords: DM, local-to-local, end
1883 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
1884 
1885 @*/
1886 PetscErrorCode  DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
1887 {
1888   PetscErrorCode          ierr;
1889 
1890   PetscFunctionBegin;
1891   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1892   ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
1893   PetscFunctionReturn(0);
1894 }
1895 
1896 
1897 #undef __FUNCT__
1898 #define __FUNCT__ "DMCoarsen"
1899 /*@
1900     DMCoarsen - Coarsens a DM object
1901 
1902     Collective on DM
1903 
1904     Input Parameter:
1905 +   dm - the DM object
1906 -   comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
1907 
1908     Output Parameter:
1909 .   dmc - the coarsened DM
1910 
1911     Level: developer
1912 
1913 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1914 
1915 @*/
1916 PetscErrorCode  DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
1917 {
1918   PetscErrorCode    ierr;
1919   DMCoarsenHookLink link;
1920 
1921   PetscFunctionBegin;
1922   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1923   ierr                      = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr);
1924   (*dmc)->ops->creatematrix = dm->ops->creatematrix;
1925   ierr                      = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr);
1926   (*dmc)->ctx               = dm->ctx;
1927   (*dmc)->levelup           = dm->levelup;
1928   (*dmc)->leveldown         = dm->leveldown + 1;
1929   ierr                      = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr);
1930   for (link=dm->coarsenhook; link; link=link->next) {
1931     if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);}
1932   }
1933   PetscFunctionReturn(0);
1934 }
1935 
1936 #undef __FUNCT__
1937 #define __FUNCT__ "DMCoarsenHookAdd"
1938 /*@C
1939    DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
1940 
1941    Logically Collective
1942 
1943    Input Arguments:
1944 +  fine - nonlinear solver context on which to run a hook when restricting to a coarser level
1945 .  coarsenhook - function to run when setting up a coarser level
1946 .  restricthook - function to run to update data on coarser levels (once per SNESSolve())
1947 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1948 
1949    Calling sequence of coarsenhook:
1950 $    coarsenhook(DM fine,DM coarse,void *ctx);
1951 
1952 +  fine - fine level DM
1953 .  coarse - coarse level DM to restrict problem to
1954 -  ctx - optional user-defined function context
1955 
1956    Calling sequence for restricthook:
1957 $    restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx)
1958 
1959 +  fine - fine level DM
1960 .  mrestrict - matrix restricting a fine-level solution to the coarse grid
1961 .  rscale - scaling vector for restriction
1962 .  inject - matrix restricting by injection
1963 .  coarse - coarse level DM to update
1964 -  ctx - optional user-defined function context
1965 
1966    Level: advanced
1967 
1968    Notes:
1969    This function is only needed if auxiliary data needs to be set up on coarse grids.
1970 
1971    If this function is called multiple times, the hooks will be run in the order they are added.
1972 
1973    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
1974    extract the finest level information from its context (instead of from the SNES).
1975 
1976    This function is currently not available from Fortran.
1977 
1978 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1979 @*/
1980 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
1981 {
1982   PetscErrorCode    ierr;
1983   DMCoarsenHookLink link,*p;
1984 
1985   PetscFunctionBegin;
1986   PetscValidHeaderSpecific(fine,DM_CLASSID,1);
1987   for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
1988   ierr               = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&link);CHKERRQ(ierr);
1989   link->coarsenhook  = coarsenhook;
1990   link->restricthook = restricthook;
1991   link->ctx          = ctx;
1992   link->next         = NULL;
1993   *p                 = link;
1994   PetscFunctionReturn(0);
1995 }
1996 
1997 #undef __FUNCT__
1998 #define __FUNCT__ "DMRestrict"
1999 /*@
2000    DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd()
2001 
2002    Collective if any hooks are
2003 
2004    Input Arguments:
2005 +  fine - finer DM to use as a base
2006 .  restrct - restriction matrix, apply using MatRestrict()
2007 .  inject - injection matrix, also use MatRestrict()
2008 -  coarse - coarer DM to update
2009 
2010    Level: developer
2011 
2012 .seealso: DMCoarsenHookAdd(), MatRestrict()
2013 @*/
2014 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse)
2015 {
2016   PetscErrorCode    ierr;
2017   DMCoarsenHookLink link;
2018 
2019   PetscFunctionBegin;
2020   for (link=fine->coarsenhook; link; link=link->next) {
2021     if (link->restricthook) {
2022       ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr);
2023     }
2024   }
2025   PetscFunctionReturn(0);
2026 }
2027 
2028 #undef __FUNCT__
2029 #define __FUNCT__ "DMSubDomainHookAdd"
2030 /*@C
2031    DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
2032 
2033    Logically Collective
2034 
2035    Input Arguments:
2036 +  global - global DM
2037 .  ddhook - function to run to pass data to the decomposition DM upon its creation
2038 .  restricthook - function to run to update data on block solve (at the beginning of the block solve)
2039 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2040 
2041 
2042    Calling sequence for ddhook:
2043 $    ddhook(DM global,DM block,void *ctx)
2044 
2045 +  global - global DM
2046 .  block  - block DM
2047 -  ctx - optional user-defined function context
2048 
2049    Calling sequence for restricthook:
2050 $    restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx)
2051 
2052 +  global - global DM
2053 .  out    - scatter to the outer (with ghost and overlap points) block vector
2054 .  in     - scatter to block vector values only owned locally
2055 .  block  - block DM
2056 -  ctx - optional user-defined function context
2057 
2058    Level: advanced
2059 
2060    Notes:
2061    This function is only needed if auxiliary data needs to be set up on subdomain DMs.
2062 
2063    If this function is called multiple times, the hooks will be run in the order they are added.
2064 
2065    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2066    extract the global information from its context (instead of from the SNES).
2067 
2068    This function is currently not available from Fortran.
2069 
2070 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2071 @*/
2072 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
2073 {
2074   PetscErrorCode      ierr;
2075   DMSubDomainHookLink link,*p;
2076 
2077   PetscFunctionBegin;
2078   PetscValidHeaderSpecific(global,DM_CLASSID,1);
2079   for (p=&global->subdomainhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2080   ierr               = PetscMalloc(sizeof(struct _DMSubDomainHookLink),&link);CHKERRQ(ierr);
2081   link->restricthook = restricthook;
2082   link->ddhook       = ddhook;
2083   link->ctx          = ctx;
2084   link->next         = NULL;
2085   *p                 = link;
2086   PetscFunctionReturn(0);
2087 }
2088 
2089 #undef __FUNCT__
2090 #define __FUNCT__ "DMSubDomainRestrict"
2091 /*@
2092    DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd()
2093 
2094    Collective if any hooks are
2095 
2096    Input Arguments:
2097 +  fine - finer DM to use as a base
2098 .  oscatter - scatter from domain global vector filling subdomain global vector with overlap
2099 .  gscatter - scatter from domain global vector filling subdomain local vector with ghosts
2100 -  coarse - coarer DM to update
2101 
2102    Level: developer
2103 
2104 .seealso: DMCoarsenHookAdd(), MatRestrict()
2105 @*/
2106 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm)
2107 {
2108   PetscErrorCode      ierr;
2109   DMSubDomainHookLink link;
2110 
2111   PetscFunctionBegin;
2112   for (link=global->subdomainhook; link; link=link->next) {
2113     if (link->restricthook) {
2114       ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr);
2115     }
2116   }
2117   PetscFunctionReturn(0);
2118 }
2119 
2120 #undef __FUNCT__
2121 #define __FUNCT__ "DMGetCoarsenLevel"
2122 /*@
2123     DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM.
2124 
2125     Not Collective
2126 
2127     Input Parameter:
2128 .   dm - the DM object
2129 
2130     Output Parameter:
2131 .   level - number of coarsenings
2132 
2133     Level: developer
2134 
2135 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2136 
2137 @*/
2138 PetscErrorCode  DMGetCoarsenLevel(DM dm,PetscInt *level)
2139 {
2140   PetscFunctionBegin;
2141   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2142   *level = dm->leveldown;
2143   PetscFunctionReturn(0);
2144 }
2145 
2146 
2147 
2148 #undef __FUNCT__
2149 #define __FUNCT__ "DMRefineHierarchy"
2150 /*@C
2151     DMRefineHierarchy - Refines a DM object, all levels at once
2152 
2153     Collective on DM
2154 
2155     Input Parameter:
2156 +   dm - the DM object
2157 -   nlevels - the number of levels of refinement
2158 
2159     Output Parameter:
2160 .   dmf - the refined DM hierarchy
2161 
2162     Level: developer
2163 
2164 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2165 
2166 @*/
2167 PetscErrorCode  DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
2168 {
2169   PetscErrorCode ierr;
2170 
2171   PetscFunctionBegin;
2172   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2173   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2174   if (nlevels == 0) PetscFunctionReturn(0);
2175   if (dm->ops->refinehierarchy) {
2176     ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr);
2177   } else if (dm->ops->refine) {
2178     PetscInt i;
2179 
2180     ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr);
2181     for (i=1; i<nlevels; i++) {
2182       ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr);
2183     }
2184   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
2185   PetscFunctionReturn(0);
2186 }
2187 
2188 #undef __FUNCT__
2189 #define __FUNCT__ "DMCoarsenHierarchy"
2190 /*@C
2191     DMCoarsenHierarchy - Coarsens a DM object, all levels at once
2192 
2193     Collective on DM
2194 
2195     Input Parameter:
2196 +   dm - the DM object
2197 -   nlevels - the number of levels of coarsening
2198 
2199     Output Parameter:
2200 .   dmc - the coarsened DM hierarchy
2201 
2202     Level: developer
2203 
2204 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2205 
2206 @*/
2207 PetscErrorCode  DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
2208 {
2209   PetscErrorCode ierr;
2210 
2211   PetscFunctionBegin;
2212   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2213   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2214   if (nlevels == 0) PetscFunctionReturn(0);
2215   PetscValidPointer(dmc,3);
2216   if (dm->ops->coarsenhierarchy) {
2217     ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr);
2218   } else if (dm->ops->coarsen) {
2219     PetscInt i;
2220 
2221     ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr);
2222     for (i=1; i<nlevels; i++) {
2223       ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr);
2224     }
2225   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
2226   PetscFunctionReturn(0);
2227 }
2228 
2229 #undef __FUNCT__
2230 #define __FUNCT__ "DMCreateAggregates"
2231 /*@
2232    DMCreateAggregates - Gets the aggregates that map between
2233    grids associated with two DMs.
2234 
2235    Collective on DM
2236 
2237    Input Parameters:
2238 +  dmc - the coarse grid DM
2239 -  dmf - the fine grid DM
2240 
2241    Output Parameters:
2242 .  rest - the restriction matrix (transpose of the projection matrix)
2243 
2244    Level: intermediate
2245 
2246 .keywords: interpolation, restriction, multigrid
2247 
2248 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation()
2249 @*/
2250 PetscErrorCode  DMCreateAggregates(DM dmc, DM dmf, Mat *rest)
2251 {
2252   PetscErrorCode ierr;
2253 
2254   PetscFunctionBegin;
2255   PetscValidHeaderSpecific(dmc,DM_CLASSID,1);
2256   PetscValidHeaderSpecific(dmf,DM_CLASSID,2);
2257   ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr);
2258   PetscFunctionReturn(0);
2259 }
2260 
2261 #undef __FUNCT__
2262 #define __FUNCT__ "DMSetApplicationContextDestroy"
2263 /*@C
2264     DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed
2265 
2266     Not Collective
2267 
2268     Input Parameters:
2269 +   dm - the DM object
2270 -   destroy - the destroy function
2271 
2272     Level: intermediate
2273 
2274 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2275 
2276 @*/
2277 PetscErrorCode  DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**))
2278 {
2279   PetscFunctionBegin;
2280   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2281   dm->ctxdestroy = destroy;
2282   PetscFunctionReturn(0);
2283 }
2284 
2285 #undef __FUNCT__
2286 #define __FUNCT__ "DMSetApplicationContext"
2287 /*@
2288     DMSetApplicationContext - Set a user context into a DM object
2289 
2290     Not Collective
2291 
2292     Input Parameters:
2293 +   dm - the DM object
2294 -   ctx - the user context
2295 
2296     Level: intermediate
2297 
2298 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2299 
2300 @*/
2301 PetscErrorCode  DMSetApplicationContext(DM dm,void *ctx)
2302 {
2303   PetscFunctionBegin;
2304   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2305   dm->ctx = ctx;
2306   PetscFunctionReturn(0);
2307 }
2308 
2309 #undef __FUNCT__
2310 #define __FUNCT__ "DMGetApplicationContext"
2311 /*@
2312     DMGetApplicationContext - Gets a user context from a DM object
2313 
2314     Not Collective
2315 
2316     Input Parameter:
2317 .   dm - the DM object
2318 
2319     Output Parameter:
2320 .   ctx - the user context
2321 
2322     Level: intermediate
2323 
2324 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2325 
2326 @*/
2327 PetscErrorCode  DMGetApplicationContext(DM dm,void *ctx)
2328 {
2329   PetscFunctionBegin;
2330   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2331   *(void**)ctx = dm->ctx;
2332   PetscFunctionReturn(0);
2333 }
2334 
2335 #undef __FUNCT__
2336 #define __FUNCT__ "DMSetVariableBounds"
2337 /*@C
2338     DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI.
2339 
2340     Logically Collective on DM
2341 
2342     Input Parameter:
2343 +   dm - the DM object
2344 -   f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set)
2345 
2346     Level: intermediate
2347 
2348 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(),
2349          DMSetJacobian()
2350 
2351 @*/
2352 PetscErrorCode  DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
2353 {
2354   PetscFunctionBegin;
2355   dm->ops->computevariablebounds = f;
2356   PetscFunctionReturn(0);
2357 }
2358 
2359 #undef __FUNCT__
2360 #define __FUNCT__ "DMHasVariableBounds"
2361 /*@
2362     DMHasVariableBounds - does the DM object have a variable bounds function?
2363 
2364     Not Collective
2365 
2366     Input Parameter:
2367 .   dm - the DM object to destroy
2368 
2369     Output Parameter:
2370 .   flg - PETSC_TRUE if the variable bounds function exists
2371 
2372     Level: developer
2373 
2374 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2375 
2376 @*/
2377 PetscErrorCode  DMHasVariableBounds(DM dm,PetscBool  *flg)
2378 {
2379   PetscFunctionBegin;
2380   *flg =  (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
2381   PetscFunctionReturn(0);
2382 }
2383 
2384 #undef __FUNCT__
2385 #define __FUNCT__ "DMComputeVariableBounds"
2386 /*@C
2387     DMComputeVariableBounds - compute variable bounds used by SNESVI.
2388 
2389     Logically Collective on DM
2390 
2391     Input Parameters:
2392 +   dm - the DM object to destroy
2393 -   x  - current solution at which the bounds are computed
2394 
2395     Output parameters:
2396 +   xl - lower bound
2397 -   xu - upper bound
2398 
2399     Level: intermediate
2400 
2401 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2402 
2403 @*/
2404 PetscErrorCode  DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
2405 {
2406   PetscErrorCode ierr;
2407 
2408   PetscFunctionBegin;
2409   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
2410   PetscValidHeaderSpecific(xu,VEC_CLASSID,2);
2411   if (dm->ops->computevariablebounds) {
2412     ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr);
2413   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds.");
2414   PetscFunctionReturn(0);
2415 }
2416 
2417 #undef __FUNCT__
2418 #define __FUNCT__ "DMHasColoring"
2419 /*@
2420     DMHasColoring - does the DM object have a method of providing a coloring?
2421 
2422     Not Collective
2423 
2424     Input Parameter:
2425 .   dm - the DM object
2426 
2427     Output Parameter:
2428 .   flg - PETSC_TRUE if the DM has facilities for DMCreateColoring().
2429 
2430     Level: developer
2431 
2432 .seealso DMHasFunction(), DMCreateColoring()
2433 
2434 @*/
2435 PetscErrorCode  DMHasColoring(DM dm,PetscBool  *flg)
2436 {
2437   PetscFunctionBegin;
2438   *flg =  (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
2439   PetscFunctionReturn(0);
2440 }
2441 
2442 #undef  __FUNCT__
2443 #define __FUNCT__ "DMSetVec"
2444 /*@C
2445     DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear.
2446 
2447     Collective on DM
2448 
2449     Input Parameter:
2450 +   dm - the DM object
2451 -   x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems.
2452 
2453     Level: developer
2454 
2455 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2456 
2457 @*/
2458 PetscErrorCode  DMSetVec(DM dm,Vec x)
2459 {
2460   PetscErrorCode ierr;
2461 
2462   PetscFunctionBegin;
2463   if (x) {
2464     if (!dm->x) {
2465       ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr);
2466     }
2467     ierr = VecCopy(x,dm->x);CHKERRQ(ierr);
2468   } else if (dm->x) {
2469     ierr = VecDestroy(&dm->x);CHKERRQ(ierr);
2470   }
2471   PetscFunctionReturn(0);
2472 }
2473 
2474 PetscFunctionList DMList              = NULL;
2475 PetscBool         DMRegisterAllCalled = PETSC_FALSE;
2476 
2477 #undef __FUNCT__
2478 #define __FUNCT__ "DMSetType"
2479 /*@C
2480   DMSetType - Builds a DM, for a particular DM implementation.
2481 
2482   Collective on DM
2483 
2484   Input Parameters:
2485 + dm     - The DM object
2486 - method - The name of the DM type
2487 
2488   Options Database Key:
2489 . -dm_type <type> - Sets the DM type; use -help for a list of available types
2490 
2491   Notes:
2492   See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).
2493 
2494   Level: intermediate
2495 
2496 .keywords: DM, set, type
2497 .seealso: DMGetType(), DMCreate()
2498 @*/
2499 PetscErrorCode  DMSetType(DM dm, DMType method)
2500 {
2501   PetscErrorCode (*r)(DM);
2502   PetscBool      match;
2503   PetscErrorCode ierr;
2504 
2505   PetscFunctionBegin;
2506   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
2507   ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr);
2508   if (match) PetscFunctionReturn(0);
2509 
2510   if (!DMRegisterAllCalled) {ierr = DMRegisterAll();CHKERRQ(ierr);}
2511   ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr);
2512   if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
2513 
2514   if (dm->ops->destroy) {
2515     ierr             = (*dm->ops->destroy)(dm);CHKERRQ(ierr);
2516     dm->ops->destroy = NULL;
2517   }
2518   ierr = (*r)(dm);CHKERRQ(ierr);
2519   ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr);
2520   PetscFunctionReturn(0);
2521 }
2522 
2523 #undef __FUNCT__
2524 #define __FUNCT__ "DMGetType"
2525 /*@C
2526   DMGetType - Gets the DM type name (as a string) from the DM.
2527 
2528   Not Collective
2529 
2530   Input Parameter:
2531 . dm  - The DM
2532 
2533   Output Parameter:
2534 . type - The DM type name
2535 
2536   Level: intermediate
2537 
2538 .keywords: DM, get, type, name
2539 .seealso: DMSetType(), DMCreate()
2540 @*/
2541 PetscErrorCode  DMGetType(DM dm, DMType *type)
2542 {
2543   PetscErrorCode ierr;
2544 
2545   PetscFunctionBegin;
2546   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
2547   PetscValidPointer(type,2);
2548   if (!DMRegisterAllCalled) {
2549     ierr = DMRegisterAll();CHKERRQ(ierr);
2550   }
2551   *type = ((PetscObject)dm)->type_name;
2552   PetscFunctionReturn(0);
2553 }
2554 
2555 #undef __FUNCT__
2556 #define __FUNCT__ "DMConvert"
2557 /*@C
2558   DMConvert - Converts a DM to another DM, either of the same or different type.
2559 
2560   Collective on DM
2561 
2562   Input Parameters:
2563 + dm - the DM
2564 - newtype - new DM type (use "same" for the same type)
2565 
2566   Output Parameter:
2567 . M - pointer to new DM
2568 
2569   Notes:
2570   Cannot be used to convert a sequential DM to parallel or parallel to sequential,
2571   the MPI communicator of the generated DM is always the same as the communicator
2572   of the input DM.
2573 
2574   Level: intermediate
2575 
2576 .seealso: DMCreate()
2577 @*/
2578 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
2579 {
2580   DM             B;
2581   char           convname[256];
2582   PetscBool      sametype, issame;
2583   PetscErrorCode ierr;
2584 
2585   PetscFunctionBegin;
2586   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2587   PetscValidType(dm,1);
2588   PetscValidPointer(M,3);
2589   ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr);
2590   ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr);
2591   {
2592     PetscErrorCode (*conv)(DM, DMType, DM*) = NULL;
2593 
2594     /*
2595        Order of precedence:
2596        1) See if a specialized converter is known to the current DM.
2597        2) See if a specialized converter is known to the desired DM class.
2598        3) See if a good general converter is registered for the desired class
2599        4) See if a good general converter is known for the current matrix.
2600        5) Use a really basic converter.
2601     */
2602 
2603     /* 1) See if a specialized converter is known to the current DM and the desired class */
2604     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
2605     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
2606     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
2607     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
2608     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
2609     ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr);
2610     if (conv) goto foundconv;
2611 
2612     /* 2)  See if a specialized converter is known to the desired DM class. */
2613     ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr);
2614     ierr = DMSetType(B, newtype);CHKERRQ(ierr);
2615     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
2616     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
2617     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
2618     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
2619     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
2620     ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr);
2621     if (conv) {
2622       ierr = DMDestroy(&B);CHKERRQ(ierr);
2623       goto foundconv;
2624     }
2625 
2626 #if 0
2627     /* 3) See if a good general converter is registered for the desired class */
2628     conv = B->ops->convertfrom;
2629     ierr = DMDestroy(&B);CHKERRQ(ierr);
2630     if (conv) goto foundconv;
2631 
2632     /* 4) See if a good general converter is known for the current matrix */
2633     if (dm->ops->convert) {
2634       conv = dm->ops->convert;
2635     }
2636     if (conv) goto foundconv;
2637 #endif
2638 
2639     /* 5) Use a really basic converter. */
2640     SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);
2641 
2642 foundconv:
2643     ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
2644     ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr);
2645     ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
2646   }
2647   ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr);
2648   PetscFunctionReturn(0);
2649 }
2650 
2651 /*--------------------------------------------------------------------------------------------------------------------*/
2652 
2653 #undef __FUNCT__
2654 #define __FUNCT__ "DMRegister"
2655 /*@C
2656   DMRegister -  Adds a new DM component implementation
2657 
2658   Not Collective
2659 
2660   Input Parameters:
2661 + name        - The name of a new user-defined creation routine
2662 - create_func - The creation routine itself
2663 
2664   Notes:
2665   DMRegister() may be called multiple times to add several user-defined DMs
2666 
2667 
2668   Sample usage:
2669 .vb
2670     DMRegister("my_da", MyDMCreate);
2671 .ve
2672 
2673   Then, your DM type can be chosen with the procedural interface via
2674 .vb
2675     DMCreate(MPI_Comm, DM *);
2676     DMSetType(DM,"my_da");
2677 .ve
2678    or at runtime via the option
2679 .vb
2680     -da_type my_da
2681 .ve
2682 
2683   Level: advanced
2684 
2685 .keywords: DM, register
2686 .seealso: DMRegisterAll(), DMRegisterDestroy()
2687 
2688 @*/
2689 PetscErrorCode  DMRegister(const char sname[],PetscErrorCode (*function)(DM))
2690 {
2691   PetscErrorCode ierr;
2692 
2693   PetscFunctionBegin;
2694   ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr);
2695   PetscFunctionReturn(0);
2696 }
2697 
2698 #undef __FUNCT__
2699 #define __FUNCT__ "DMLoad"
2700 /*@C
2701   DMLoad - Loads a DM that has been stored in binary  with DMView().
2702 
2703   Collective on PetscViewer
2704 
2705   Input Parameters:
2706 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
2707            some related function before a call to DMLoad().
2708 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
2709            HDF5 file viewer, obtained from PetscViewerHDF5Open()
2710 
2711    Level: intermediate
2712 
2713   Notes:
2714    The type is determined by the data in the file, any type set into the DM before this call is ignored.
2715 
2716   Notes for advanced users:
2717   Most users should not need to know the details of the binary storage
2718   format, since DMLoad() and DMView() completely hide these details.
2719   But for anyone who's interested, the standard binary matrix storage
2720   format is
2721 .vb
2722      has not yet been determined
2723 .ve
2724 
2725 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad()
2726 @*/
2727 PetscErrorCode  DMLoad(DM newdm, PetscViewer viewer)
2728 {
2729   PetscBool      isbinary, ishdf5;
2730   PetscErrorCode ierr;
2731 
2732   PetscFunctionBegin;
2733   PetscValidHeaderSpecific(newdm,DM_CLASSID,1);
2734   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
2735   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
2736   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
2737   if (isbinary) {
2738     PetscInt classid;
2739     char     type[256];
2740 
2741     ierr = PetscViewerBinaryRead(viewer,&classid,1,PETSC_INT);CHKERRQ(ierr);
2742     if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid);
2743     ierr = PetscViewerBinaryRead(viewer,type,256,PETSC_CHAR);CHKERRQ(ierr);
2744     ierr = DMSetType(newdm, type);CHKERRQ(ierr);
2745     if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);}
2746   } else if (ishdf5) {
2747     if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);}
2748   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
2749   PetscFunctionReturn(0);
2750 }
2751 
2752 /******************************** FEM Support **********************************/
2753 
2754 #undef __FUNCT__
2755 #define __FUNCT__ "DMPrintCellVector"
2756 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
2757 {
2758   PetscInt       f;
2759   PetscErrorCode ierr;
2760 
2761   PetscFunctionBegin;
2762   ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
2763   for (f = 0; f < len; ++f) {
2764     ierr = PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr);
2765   }
2766   PetscFunctionReturn(0);
2767 }
2768 
2769 #undef __FUNCT__
2770 #define __FUNCT__ "DMPrintCellMatrix"
2771 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
2772 {
2773   PetscInt       f, g;
2774   PetscErrorCode ierr;
2775 
2776   PetscFunctionBegin;
2777   ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
2778   for (f = 0; f < rows; ++f) {
2779     ierr = PetscPrintf(PETSC_COMM_SELF, "  |");CHKERRQ(ierr);
2780     for (g = 0; g < cols; ++g) {
2781       ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr);
2782     }
2783     ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr);
2784   }
2785   PetscFunctionReturn(0);
2786 }
2787 
2788 #undef __FUNCT__
2789 #define __FUNCT__ "DMPrintLocalVec"
2790 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
2791 {
2792   PetscMPIInt    rank, numProcs;
2793   PetscInt       p;
2794   PetscErrorCode ierr;
2795 
2796   PetscFunctionBegin;
2797   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr);
2798   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr);
2799   ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "%s:\n", name);CHKERRQ(ierr);
2800   for (p = 0; p < numProcs; ++p) {
2801     if (p == rank) {
2802       Vec x;
2803 
2804       ierr = VecDuplicate(X, &x);CHKERRQ(ierr);
2805       ierr = VecCopy(X, x);CHKERRQ(ierr);
2806       ierr = VecChop(x, tol);CHKERRQ(ierr);
2807       ierr = VecView(x, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2808       ierr = VecDestroy(&x);CHKERRQ(ierr);
2809       ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2810     }
2811     ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr);
2812   }
2813   PetscFunctionReturn(0);
2814 }
2815 
2816 #undef __FUNCT__
2817 #define __FUNCT__ "DMGetDefaultSection"
2818 /*@
2819   DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM.
2820 
2821   Input Parameter:
2822 . dm - The DM
2823 
2824   Output Parameter:
2825 . section - The PetscSection
2826 
2827   Level: intermediate
2828 
2829   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
2830 
2831 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
2832 @*/
2833 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section)
2834 {
2835   PetscErrorCode ierr;
2836 
2837   PetscFunctionBegin;
2838   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2839   PetscValidPointer(section, 2);
2840   if (!dm->defaultSection && dm->ops->createdefaultsection) {ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr);}
2841   *section = dm->defaultSection;
2842   PetscFunctionReturn(0);
2843 }
2844 
2845 #undef __FUNCT__
2846 #define __FUNCT__ "DMSetDefaultSection"
2847 /*@
2848   DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM.
2849 
2850   Input Parameters:
2851 + dm - The DM
2852 - section - The PetscSection
2853 
2854   Level: intermediate
2855 
2856   Note: Any existing Section will be destroyed
2857 
2858 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
2859 @*/
2860 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section)
2861 {
2862   PetscInt       numFields;
2863   PetscInt       f;
2864   PetscErrorCode ierr;
2865 
2866   PetscFunctionBegin;
2867   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2868   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
2869   ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
2870   ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr);
2871   dm->defaultSection = section;
2872   ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);
2873   if (numFields) {
2874     ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr);
2875     for (f = 0; f < numFields; ++f) {
2876       PetscObject disc;
2877       const char *name;
2878 
2879       ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr);
2880       ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr);
2881       ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr);
2882     }
2883   }
2884   /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */
2885   ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr);
2886   PetscFunctionReturn(0);
2887 }
2888 
2889 #undef __FUNCT__
2890 #define __FUNCT__ "DMGetDefaultGlobalSection"
2891 /*@
2892   DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM.
2893 
2894   Collective on DM
2895 
2896   Input Parameter:
2897 . dm - The DM
2898 
2899   Output Parameter:
2900 . section - The PetscSection
2901 
2902   Level: intermediate
2903 
2904   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
2905 
2906 .seealso: DMSetDefaultSection(), DMGetDefaultSection()
2907 @*/
2908 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section)
2909 {
2910   PetscErrorCode ierr;
2911 
2912   PetscFunctionBegin;
2913   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2914   PetscValidPointer(section, 2);
2915   if (!dm->defaultGlobalSection) {
2916     PetscSection s;
2917 
2918     ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
2919     if (!s)  SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
2920     if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection");
2921     ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr);
2922     ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr);
2923     ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr);
2924   }
2925   *section = dm->defaultGlobalSection;
2926   PetscFunctionReturn(0);
2927 }
2928 
2929 #undef __FUNCT__
2930 #define __FUNCT__ "DMSetDefaultGlobalSection"
2931 /*@
2932   DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM.
2933 
2934   Input Parameters:
2935 + dm - The DM
2936 - section - The PetscSection, or NULL
2937 
2938   Level: intermediate
2939 
2940   Note: Any existing Section will be destroyed
2941 
2942 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection()
2943 @*/
2944 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section)
2945 {
2946   PetscErrorCode ierr;
2947 
2948   PetscFunctionBegin;
2949   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2950   if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
2951   ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
2952   ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr);
2953   dm->defaultGlobalSection = section;
2954   PetscFunctionReturn(0);
2955 }
2956 
2957 #undef __FUNCT__
2958 #define __FUNCT__ "DMGetDefaultSF"
2959 /*@
2960   DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set,
2961   it is created from the default PetscSection layouts in the DM.
2962 
2963   Input Parameter:
2964 . dm - The DM
2965 
2966   Output Parameter:
2967 . sf - The PetscSF
2968 
2969   Level: intermediate
2970 
2971   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
2972 
2973 .seealso: DMSetDefaultSF(), DMCreateDefaultSF()
2974 @*/
2975 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf)
2976 {
2977   PetscInt       nroots;
2978   PetscErrorCode ierr;
2979 
2980   PetscFunctionBegin;
2981   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2982   PetscValidPointer(sf, 2);
2983   ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
2984   if (nroots < 0) {
2985     PetscSection section, gSection;
2986 
2987     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
2988     if (section) {
2989       ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr);
2990       ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr);
2991     } else {
2992       *sf = NULL;
2993       PetscFunctionReturn(0);
2994     }
2995   }
2996   *sf = dm->defaultSF;
2997   PetscFunctionReturn(0);
2998 }
2999 
3000 #undef __FUNCT__
3001 #define __FUNCT__ "DMSetDefaultSF"
3002 /*@
3003   DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM
3004 
3005   Input Parameters:
3006 + dm - The DM
3007 - sf - The PetscSF
3008 
3009   Level: intermediate
3010 
3011   Note: Any previous SF is destroyed
3012 
3013 .seealso: DMGetDefaultSF(), DMCreateDefaultSF()
3014 @*/
3015 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf)
3016 {
3017   PetscErrorCode ierr;
3018 
3019   PetscFunctionBegin;
3020   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3021   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
3022   ierr          = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr);
3023   dm->defaultSF = sf;
3024   PetscFunctionReturn(0);
3025 }
3026 
3027 #undef __FUNCT__
3028 #define __FUNCT__ "DMCreateDefaultSF"
3029 /*@C
3030   DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections
3031   describing the data layout.
3032 
3033   Input Parameters:
3034 + dm - The DM
3035 . localSection - PetscSection describing the local data layout
3036 - globalSection - PetscSection describing the global data layout
3037 
3038   Level: intermediate
3039 
3040 .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3041 @*/
3042 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection)
3043 {
3044   MPI_Comm       comm;
3045   PetscLayout    layout;
3046   const PetscInt *ranges;
3047   PetscInt       *local;
3048   PetscSFNode    *remote;
3049   PetscInt       pStart, pEnd, p, nroots, nleaves = 0, l;
3050   PetscMPIInt    size, rank;
3051   PetscErrorCode ierr;
3052 
3053   PetscFunctionBegin;
3054   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
3055   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3056   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
3057   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3058   ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr);
3059   ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr);
3060   ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
3061   ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
3062   ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr);
3063   ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
3064   ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
3065   for (p = pStart; p < pEnd; ++p) {
3066     PetscInt gdof, gcdof;
3067 
3068     ierr     = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3069     ierr     = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3070     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));
3071     nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3072   }
3073   ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr);
3074   ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr);
3075   for (p = pStart, l = 0; p < pEnd; ++p) {
3076     const PetscInt *cind;
3077     PetscInt       dof, cdof, off, gdof, gcdof, goff, gsize, d, c;
3078 
3079     ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr);
3080     ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr);
3081     ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr);
3082     ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr);
3083     ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3084     ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3085     ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr);
3086     if (!gdof) continue; /* Censored point */
3087     gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3088     if (gsize != dof-cdof) {
3089       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);
3090       cdof = 0; /* Ignore constraints */
3091     }
3092     for (d = 0, c = 0; d < dof; ++d) {
3093       if ((c < cdof) && (cind[c] == d)) {++c; continue;}
3094       local[l+d-c] = off+d;
3095     }
3096     if (gdof < 0) {
3097       for (d = 0; d < gsize; ++d, ++l) {
3098         PetscInt offset = -(goff+1) + d, r;
3099 
3100         ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr);
3101         if (r < 0) r = -(r+2);
3102         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);
3103         remote[l].rank  = r;
3104         remote[l].index = offset - ranges[r];
3105       }
3106     } else {
3107       for (d = 0; d < gsize; ++d, ++l) {
3108         remote[l].rank  = rank;
3109         remote[l].index = goff+d - ranges[rank];
3110       }
3111     }
3112   }
3113   if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves);
3114   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
3115   ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr);
3116   PetscFunctionReturn(0);
3117 }
3118 
3119 #undef __FUNCT__
3120 #define __FUNCT__ "DMGetPointSF"
3121 /*@
3122   DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM.
3123 
3124   Input Parameter:
3125 . dm - The DM
3126 
3127   Output Parameter:
3128 . sf - The PetscSF
3129 
3130   Level: intermediate
3131 
3132   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3133 
3134 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3135 @*/
3136 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
3137 {
3138   PetscFunctionBegin;
3139   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3140   PetscValidPointer(sf, 2);
3141   *sf = dm->sf;
3142   PetscFunctionReturn(0);
3143 }
3144 
3145 #undef __FUNCT__
3146 #define __FUNCT__ "DMSetPointSF"
3147 /*@
3148   DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM.
3149 
3150   Input Parameters:
3151 + dm - The DM
3152 - sf - The PetscSF
3153 
3154   Level: intermediate
3155 
3156 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3157 @*/
3158 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
3159 {
3160   PetscErrorCode ierr;
3161 
3162   PetscFunctionBegin;
3163   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3164   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
3165   ierr   = PetscSFDestroy(&dm->sf);CHKERRQ(ierr);
3166   ierr   = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr);
3167   dm->sf = sf;
3168   PetscFunctionReturn(0);
3169 }
3170 
3171 #undef __FUNCT__
3172 #define __FUNCT__ "DMGetDS"
3173 /*@
3174   DMGetDS - Get the PetscDS
3175 
3176   Input Parameter:
3177 . dm - The DM
3178 
3179   Output Parameter:
3180 . prob - The PetscDS
3181 
3182   Level: developer
3183 
3184 .seealso: DMSetDS()
3185 @*/
3186 PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
3187 {
3188   PetscFunctionBegin;
3189   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3190   PetscValidPointer(prob, 2);
3191   *prob = dm->prob;
3192   PetscFunctionReturn(0);
3193 }
3194 
3195 #undef __FUNCT__
3196 #define __FUNCT__ "DMSetDS"
3197 /*@
3198   DMSetDS - Set the PetscDS
3199 
3200   Input Parameters:
3201 + dm - The DM
3202 - prob - The PetscDS
3203 
3204   Level: developer
3205 
3206 .seealso: DMGetDS()
3207 @*/
3208 PetscErrorCode DMSetDS(DM dm, PetscDS prob)
3209 {
3210   PetscErrorCode ierr;
3211 
3212   PetscFunctionBegin;
3213   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3214   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2);
3215   ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr);
3216   dm->prob = prob;
3217   ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr);
3218   PetscFunctionReturn(0);
3219 }
3220 
3221 #undef __FUNCT__
3222 #define __FUNCT__ "DMGetNumFields"
3223 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
3224 {
3225   PetscErrorCode ierr;
3226 
3227   PetscFunctionBegin;
3228   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3229   ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr);
3230   PetscFunctionReturn(0);
3231 }
3232 
3233 #undef __FUNCT__
3234 #define __FUNCT__ "DMSetNumFields"
3235 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
3236 {
3237   PetscInt       Nf, f;
3238   PetscErrorCode ierr;
3239 
3240   PetscFunctionBegin;
3241   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3242   ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr);
3243   for (f = Nf; f < numFields; ++f) {
3244     PetscContainer obj;
3245 
3246     ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr);
3247     ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr);
3248     ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr);
3249   }
3250   PetscFunctionReturn(0);
3251 }
3252 
3253 #undef __FUNCT__
3254 #define __FUNCT__ "DMGetField"
3255 /*@
3256   DMGetField - Return the discretization object for a given DM field
3257 
3258   Not collective
3259 
3260   Input Parameters:
3261 + dm - The DM
3262 - f  - The field number
3263 
3264   Output Parameter:
3265 . field - The discretization object
3266 
3267   Level: developer
3268 
3269 .seealso: DMSetField()
3270 @*/
3271 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field)
3272 {
3273   PetscErrorCode ierr;
3274 
3275   PetscFunctionBegin;
3276   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3277   ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr);
3278   PetscFunctionReturn(0);
3279 }
3280 
3281 #undef __FUNCT__
3282 #define __FUNCT__ "DMSetField"
3283 /*@
3284   DMSetField - Set the discretization object for a given DM field
3285 
3286   Logically collective on DM
3287 
3288   Input Parameters:
3289 + dm - The DM
3290 . f  - The field number
3291 - field - The discretization object
3292 
3293   Level: developer
3294 
3295 .seealso: DMGetField()
3296 @*/
3297 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field)
3298 {
3299   PetscErrorCode ierr;
3300 
3301   PetscFunctionBegin;
3302   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3303   ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr);
3304   PetscFunctionReturn(0);
3305 }
3306 
3307 #undef __FUNCT__
3308 #define __FUNCT__ "DMRestrictHook_Coordinates"
3309 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx)
3310 {
3311   DM dm_coord,dmc_coord;
3312   PetscErrorCode ierr;
3313   Vec coords,ccoords;
3314   VecScatter scat;
3315   PetscFunctionBegin;
3316   ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr);
3317   ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr);
3318   ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
3319   ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr);
3320   if (coords && !ccoords) {
3321     ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr);
3322     ierr = DMCreateInjection(dmc_coord,dm_coord,&scat);CHKERRQ(ierr);
3323     ierr = VecScatterBegin(scat,coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3324     ierr = VecScatterEnd(scat,coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3325     ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr);
3326     ierr = VecScatterDestroy(&scat);CHKERRQ(ierr);
3327     ierr = VecDestroy(&ccoords);CHKERRQ(ierr);
3328   }
3329   PetscFunctionReturn(0);
3330 }
3331 
3332 #undef __FUNCT__
3333 #define __FUNCT__ "DMSubDomainHook_Coordinates"
3334 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx)
3335 {
3336   DM dm_coord,subdm_coord;
3337   PetscErrorCode ierr;
3338   Vec coords,ccoords,clcoords;
3339   VecScatter *scat_i,*scat_g;
3340   PetscFunctionBegin;
3341   ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr);
3342   ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr);
3343   ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
3344   ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr);
3345   if (coords && !ccoords) {
3346     ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr);
3347     ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr);
3348     ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr);
3349     ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3350     ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3351     ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3352     ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3353     ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr);
3354     ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr);
3355     ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr);
3356     ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr);
3357     ierr = VecDestroy(&ccoords);CHKERRQ(ierr);
3358     ierr = VecDestroy(&clcoords);CHKERRQ(ierr);
3359     ierr = PetscFree(scat_i);CHKERRQ(ierr);
3360     ierr = PetscFree(scat_g);CHKERRQ(ierr);
3361   }
3362   PetscFunctionReturn(0);
3363 }
3364 
3365 #undef __FUNCT__
3366 #define __FUNCT__ "DMSetCoordinates"
3367 /*@
3368   DMSetCoordinates - Sets into the DM a global vector that holds the coordinates
3369 
3370   Collective on DM
3371 
3372   Input Parameters:
3373 + dm - the DM
3374 - c - coordinate vector
3375 
3376   Note:
3377   The coordinates do include those for ghost points, which are in the local vector
3378 
3379   Level: intermediate
3380 
3381 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3382 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM()
3383 @*/
3384 PetscErrorCode DMSetCoordinates(DM dm, Vec c)
3385 {
3386   PetscErrorCode ierr;
3387 
3388   PetscFunctionBegin;
3389   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3390   PetscValidHeaderSpecific(c,VEC_CLASSID,2);
3391   ierr            = PetscObjectReference((PetscObject) c);CHKERRQ(ierr);
3392   ierr            = VecDestroy(&dm->coordinates);CHKERRQ(ierr);
3393   dm->coordinates = c;
3394   ierr            = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr);
3395   ierr            = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr);
3396   ierr            = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr);
3397   PetscFunctionReturn(0);
3398 }
3399 
3400 #undef __FUNCT__
3401 #define __FUNCT__ "DMSetCoordinatesLocal"
3402 /*@
3403   DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates
3404 
3405   Collective on DM
3406 
3407    Input Parameters:
3408 +  dm - the DM
3409 -  c - coordinate vector
3410 
3411   Note:
3412   The coordinates of ghost points can be set using DMSetCoordinates()
3413   followed by DMGetCoordinatesLocal(). This is intended to enable the
3414   setting of ghost coordinates outside of the domain.
3415 
3416   Level: intermediate
3417 
3418 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3419 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM()
3420 @*/
3421 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c)
3422 {
3423   PetscErrorCode ierr;
3424 
3425   PetscFunctionBegin;
3426   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3427   PetscValidHeaderSpecific(c,VEC_CLASSID,2);
3428   ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr);
3429   ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr);
3430 
3431   dm->coordinatesLocal = c;
3432 
3433   ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr);
3434   PetscFunctionReturn(0);
3435 }
3436 
3437 #undef __FUNCT__
3438 #define __FUNCT__ "DMGetCoordinates"
3439 /*@
3440   DMGetCoordinates - Gets a global vector with the coordinates associated with the DM.
3441 
3442   Not Collective
3443 
3444   Input Parameter:
3445 . dm - the DM
3446 
3447   Output Parameter:
3448 . c - global coordinate vector
3449 
3450   Note:
3451   This is a borrowed reference, so the user should NOT destroy this vector
3452 
3453   Each process has only the local coordinates (does NOT have the ghost coordinates).
3454 
3455   For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
3456   and (x_0,y_0,z_0,x_1,y_1,z_1...)
3457 
3458   Level: intermediate
3459 
3460 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3461 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
3462 @*/
3463 PetscErrorCode DMGetCoordinates(DM dm, Vec *c)
3464 {
3465   PetscErrorCode ierr;
3466 
3467   PetscFunctionBegin;
3468   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3469   PetscValidPointer(c,2);
3470   if (!dm->coordinates && dm->coordinatesLocal) {
3471     DM cdm = NULL;
3472 
3473     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
3474     ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr);
3475     ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr);
3476     ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr);
3477     ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr);
3478   }
3479   *c = dm->coordinates;
3480   PetscFunctionReturn(0);
3481 }
3482 
3483 #undef __FUNCT__
3484 #define __FUNCT__ "DMGetCoordinatesLocal"
3485 /*@
3486   DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM.
3487 
3488   Collective on DM
3489 
3490   Input Parameter:
3491 . dm - the DM
3492 
3493   Output Parameter:
3494 . c - coordinate vector
3495 
3496   Note:
3497   This is a borrowed reference, so the user should NOT destroy this vector
3498 
3499   Each process has the local and ghost coordinates
3500 
3501   For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
3502   and (x_0,y_0,z_0,x_1,y_1,z_1...)
3503 
3504   Level: intermediate
3505 
3506 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3507 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM()
3508 @*/
3509 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c)
3510 {
3511   PetscErrorCode ierr;
3512 
3513   PetscFunctionBegin;
3514   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3515   PetscValidPointer(c,2);
3516   if (!dm->coordinatesLocal && dm->coordinates) {
3517     DM cdm = NULL;
3518 
3519     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
3520     ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr);
3521     ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr);
3522     ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr);
3523     ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr);
3524   }
3525   *c = dm->coordinatesLocal;
3526   PetscFunctionReturn(0);
3527 }
3528 
3529 #undef __FUNCT__
3530 #define __FUNCT__ "DMGetCoordinateDM"
3531 /*@
3532   DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates
3533 
3534   Collective on DM
3535 
3536   Input Parameter:
3537 . dm - the DM
3538 
3539   Output Parameter:
3540 . cdm - coordinate DM
3541 
3542   Level: intermediate
3543 
3544 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3545 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
3546 @*/
3547 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm)
3548 {
3549   PetscErrorCode ierr;
3550 
3551   PetscFunctionBegin;
3552   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3553   PetscValidPointer(cdm,2);
3554   if (!dm->coordinateDM) {
3555     if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM");
3556     ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr);
3557   }
3558   *cdm = dm->coordinateDM;
3559   PetscFunctionReturn(0);
3560 }
3561 
3562 #undef __FUNCT__
3563 #define __FUNCT__ "DMSetCoordinateDM"
3564 /*@
3565   DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates
3566 
3567   Logically Collective on DM
3568 
3569   Input Parameters:
3570 + dm - the DM
3571 - cdm - coordinate DM
3572 
3573   Level: intermediate
3574 
3575 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3576 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
3577 @*/
3578 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm)
3579 {
3580   PetscErrorCode ierr;
3581 
3582   PetscFunctionBegin;
3583   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3584   PetscValidHeaderSpecific(cdm,DM_CLASSID,2);
3585   ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr);
3586   dm->coordinateDM = cdm;
3587   ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr);
3588   PetscFunctionReturn(0);
3589 }
3590 
3591 #undef __FUNCT__
3592 #define __FUNCT__ "DMGetCoordinateSection"
3593 /*@
3594   DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh.
3595 
3596   Not Collective
3597 
3598   Input Parameter:
3599 . dm - The DM object
3600 
3601   Output Parameter:
3602 . section - The PetscSection object
3603 
3604   Level: intermediate
3605 
3606 .keywords: mesh, coordinates
3607 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
3608 @*/
3609 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section)
3610 {
3611   DM             cdm;
3612   PetscErrorCode ierr;
3613 
3614   PetscFunctionBegin;
3615   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3616   PetscValidPointer(section, 2);
3617   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
3618   ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr);
3619   PetscFunctionReturn(0);
3620 }
3621 
3622 #undef __FUNCT__
3623 #define __FUNCT__ "DMSetCoordinateSection"
3624 /*@
3625   DMSetCoordinateSection - Set the layout of coordinate values over the mesh.
3626 
3627   Not Collective
3628 
3629   Input Parameters:
3630 + dm      - The DM object
3631 - section - The PetscSection object
3632 
3633   Level: intermediate
3634 
3635 .keywords: mesh, coordinates
3636 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
3637 @*/
3638 PetscErrorCode DMSetCoordinateSection(DM dm, PetscSection section)
3639 {
3640   DM             cdm;
3641   PetscErrorCode ierr;
3642 
3643   PetscFunctionBegin;
3644   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3645   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
3646   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
3647   ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr);
3648   PetscFunctionReturn(0);
3649 }
3650 
3651 #undef __FUNCT__
3652 #define __FUNCT__ "DMGetPeriodicity"
3653 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L)
3654 {
3655   PetscFunctionBegin;
3656   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3657   if (L)       *L       = dm->L;
3658   if (maxCell) *maxCell = dm->maxCell;
3659   PetscFunctionReturn(0);
3660 }
3661 
3662 #undef __FUNCT__
3663 #define __FUNCT__ "DMSetPeriodicity"
3664 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[])
3665 {
3666   Vec            coordinates;
3667   PetscInt       dim, d;
3668   PetscErrorCode ierr;
3669 
3670   PetscFunctionBegin;
3671   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3672   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
3673   ierr = VecGetBlockSize(coordinates, &dim);CHKERRQ(ierr);
3674   ierr = PetscMalloc1(dim,&dm->L);CHKERRQ(ierr);
3675   ierr = PetscMalloc1(dim,&dm->maxCell);CHKERRQ(ierr);
3676   for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d];}
3677   PetscFunctionReturn(0);
3678 }
3679 
3680 #undef __FUNCT__
3681 #define __FUNCT__ "DMLocatePoints"
3682 /*@
3683   DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells
3684 
3685   Not collective
3686 
3687   Input Parameters:
3688 + dm - The DM
3689 - v - The Vec of points
3690 
3691   Output Parameter:
3692 . cells - The local cell numbers for cells which contain the points
3693 
3694   Level: developer
3695 
3696 .keywords: point location, mesh
3697 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
3698 @*/
3699 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells)
3700 {
3701   PetscErrorCode ierr;
3702 
3703   PetscFunctionBegin;
3704   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3705   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
3706   PetscValidPointer(cells,3);
3707   if (dm->ops->locatepoints) {
3708     ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr);
3709   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM");
3710   PetscFunctionReturn(0);
3711 }
3712 
3713 #undef __FUNCT__
3714 #define __FUNCT__ "DMGetOutputDM"
3715 /*@
3716   DMGetOutputDM - Retrieve the DM associated with the layout for output
3717 
3718   Input Parameter:
3719 . dm - The original DM
3720 
3721   Output Parameter:
3722 . odm - The DM which provides the layout for output
3723 
3724   Level: intermediate
3725 
3726 .seealso: VecView(), DMGetDefaultGlobalSection()
3727 @*/
3728 PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
3729 {
3730   PetscSection   section;
3731   PetscBool      hasConstraints;
3732   PetscErrorCode ierr;
3733 
3734   PetscFunctionBegin;
3735   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3736   PetscValidPointer(odm,2);
3737   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
3738   ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr);
3739   if (!hasConstraints) {
3740     *odm = dm;
3741     PetscFunctionReturn(0);
3742   }
3743   if (!dm->dmBC) {
3744     PetscSection newSection, gsection;
3745     PetscSF      sf;
3746 
3747     ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr);
3748     ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr);
3749     ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr);
3750     ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr);
3751     ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr);
3752     ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, &gsection);CHKERRQ(ierr);
3753     ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr);
3754     ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr);
3755   }
3756   *odm = dm->dmBC;
3757   PetscFunctionReturn(0);
3758 }
3759 
3760 #undef __FUNCT__
3761 #define __FUNCT__ "DMGetOutputSequenceNumber"
3762 /*@
3763   DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
3764 
3765   Input Parameter:
3766 . dm - The original DM
3767 
3768   Output Parameters:
3769 + num - The output sequence number
3770 - val - The output sequence value
3771 
3772   Level: intermediate
3773 
3774   Note: This is intended for output that should appear in sequence, for instance
3775   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
3776 
3777 .seealso: VecView()
3778 @*/
3779 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
3780 {
3781   PetscFunctionBegin;
3782   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3783   if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;}
3784   if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;}
3785   PetscFunctionReturn(0);
3786 }
3787 
3788 #undef __FUNCT__
3789 #define __FUNCT__ "DMSetOutputSequenceNumber"
3790 /*@
3791   DMSetOutputSequenceNumber - Set the sequence number/value for output
3792 
3793   Input Parameters:
3794 + dm - The original DM
3795 . num - The output sequence number
3796 - val - The output sequence value
3797 
3798   Level: intermediate
3799 
3800   Note: This is intended for output that should appear in sequence, for instance
3801   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
3802 
3803 .seealso: VecView()
3804 @*/
3805 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
3806 {
3807   PetscFunctionBegin;
3808   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3809   dm->outputSequenceNum = num;
3810   dm->outputSequenceVal = val;
3811   PetscFunctionReturn(0);
3812 }
3813 
3814 #undef __FUNCT__
3815 #define __FUNCT__ "DMOutputSequenceLoad"
3816 /*@C
3817   DMOutputSequenceLoad - Retrieve the sequence value from a Viewer
3818 
3819   Input Parameters:
3820 + dm   - The original DM
3821 . name - The sequence name
3822 - num  - The output sequence number
3823 
3824   Output Parameter:
3825 . val  - The output sequence value
3826 
3827   Level: intermediate
3828 
3829   Note: This is intended for output that should appear in sequence, for instance
3830   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
3831 
3832 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView()
3833 @*/
3834 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
3835 {
3836   PetscBool      ishdf5;
3837   PetscErrorCode ierr;
3838 
3839   PetscFunctionBegin;
3840   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3841   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
3842   PetscValidPointer(val,4);
3843   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
3844   if (ishdf5) {
3845 #if defined(PETSC_HAVE_HDF5)
3846     PetscScalar value;
3847 
3848     ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr);
3849     *val = PetscRealPart(value);
3850 #endif
3851   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
3852   PetscFunctionReturn(0);
3853 }
3854