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