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