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