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