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