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