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