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