xref: /petsc/src/dm/interface/dm.c (revision f3a242be33705e5baaba9fe1b049c70d45f729b6)
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)(PetscOptionsObject,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 .   mat - 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,Mat *mat)
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,mat);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     const PetscScalar *gArray;
1687     PetscScalar       *lArray;
1688 
1689     if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1690     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1691     ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr);
1692     ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr);
1693     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1694     ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr);
1695   } else {
1696     ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
1697   }
1698   PetscFunctionReturn(0);
1699 }
1700 
1701 #undef __FUNCT__
1702 #define __FUNCT__ "DMGlobalToLocalEnd"
1703 /*@
1704     DMGlobalToLocalEnd - Ends updating local vectors from global vector
1705 
1706     Neighbor-wise Collective on DM
1707 
1708     Input Parameters:
1709 +   dm - the DM object
1710 .   g - the global vector
1711 .   mode - INSERT_VALUES or ADD_VALUES
1712 -   l - the local vector
1713 
1714 
1715     Level: beginner
1716 
1717 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
1718 
1719 @*/
1720 PetscErrorCode  DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
1721 {
1722   PetscSF                 sf;
1723   PetscErrorCode          ierr;
1724   const PetscScalar      *gArray;
1725   PetscScalar            *lArray;
1726   DMGlobalToLocalHookLink link;
1727 
1728   PetscFunctionBegin;
1729   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1730   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1731   if (sf) {
1732     if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1733 
1734     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1735     ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr);
1736     ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr);
1737     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1738     ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr);
1739   } else {
1740     ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
1741   }
1742   ierr = DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);CHKERRQ(ierr);
1743   for (link=dm->gtolhook; link; link=link->next) {
1744     if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);}
1745   }
1746   PetscFunctionReturn(0);
1747 }
1748 
1749 #undef __FUNCT__
1750 #define __FUNCT__ "DMLocalToGlobalHookAdd"
1751 /*@C
1752    DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called
1753 
1754    Logically Collective
1755 
1756    Input Arguments:
1757 +  dm - the DM
1758 .  beginhook - function to run at the beginning of DMLocalToGlobalBegin()
1759 .  endhook - function to run after DMLocalToGlobalEnd() has completed
1760 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1761 
1762    Calling sequence for beginhook:
1763 $    beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
1764 
1765 +  dm - global DM
1766 .  l - local vector
1767 .  mode - mode
1768 .  g - global vector
1769 -  ctx - optional user-defined function context
1770 
1771 
1772    Calling sequence for endhook:
1773 $    endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
1774 
1775 +  global - global DM
1776 .  l - local vector
1777 .  mode - mode
1778 .  g - global vector
1779 -  ctx - optional user-defined function context
1780 
1781    Level: advanced
1782 
1783 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1784 @*/
1785 PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
1786 {
1787   PetscErrorCode          ierr;
1788   DMLocalToGlobalHookLink link,*p;
1789 
1790   PetscFunctionBegin;
1791   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1792   for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
1793   ierr            = PetscMalloc(sizeof(struct _DMLocalToGlobalHookLink),&link);CHKERRQ(ierr);
1794   link->beginhook = beginhook;
1795   link->endhook   = endhook;
1796   link->ctx       = ctx;
1797   link->next      = NULL;
1798   *p              = link;
1799   PetscFunctionReturn(0);
1800 }
1801 
1802 #undef __FUNCT__
1803 #define __FUNCT__ "DMLocalToGlobalHook_Constraints"
1804 static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx)
1805 {
1806   Mat cMat;
1807   Vec cVec;
1808   PetscSection section, cSec;
1809   PetscInt pStart, pEnd, p, dof;
1810   PetscErrorCode ierr;
1811 
1812   PetscFunctionBegin;
1813   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1814   ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr);
1815   if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) {
1816     ierr = DMGetDefaultSection(dm,&section);CHKERRQ(ierr);
1817     ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr);
1818     ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr);
1819     for (p = pStart; p < pEnd; p++) {
1820       ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr);
1821       if (dof) {
1822         PetscInt d;
1823         PetscScalar *vals;
1824         ierr = VecGetValuesSection(l,section,p,&vals);CHKERRQ(ierr);
1825         ierr = VecSetValuesSection(cVec,cSec,p,vals,mode);CHKERRQ(ierr);
1826         /* for this to be the true transpose, we have to zero the values that
1827          * we just extracted */
1828         for (d = 0; d < dof; d++) {
1829           vals[d] = 0.;
1830         }
1831       }
1832     }
1833     ierr = MatMultTransposeAdd(cMat,cVec,l,l);CHKERRQ(ierr);
1834     ierr = VecDestroy(&cVec);CHKERRQ(ierr);
1835   }
1836   PetscFunctionReturn(0);
1837 }
1838 
1839 #undef __FUNCT__
1840 #define __FUNCT__ "DMLocalToGlobalBegin"
1841 /*@
1842     DMLocalToGlobalBegin - updates global vectors from local vectors
1843 
1844     Neighbor-wise Collective on DM
1845 
1846     Input Parameters:
1847 +   dm - the DM object
1848 .   l - the local vector
1849 .   mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that base point.
1850 -   g - the global vector
1851 
1852     Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation.
1853            INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one.
1854 
1855     Level: beginner
1856 
1857 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()
1858 
1859 @*/
1860 PetscErrorCode  DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
1861 {
1862   PetscSF                 sf;
1863   PetscSection            s, gs;
1864   DMLocalToGlobalHookLink link;
1865   const PetscScalar      *lArray;
1866   PetscScalar            *gArray;
1867   PetscBool               isInsert;
1868   PetscErrorCode          ierr;
1869 
1870   PetscFunctionBegin;
1871   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1872   for (link=dm->ltoghook; link; link=link->next) {
1873     if (link->beginhook) {
1874       ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr);
1875     }
1876   }
1877   ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr);
1878   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1879   ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
1880   switch (mode) {
1881   case INSERT_VALUES:
1882   case INSERT_ALL_VALUES:
1883     isInsert = PETSC_TRUE; break;
1884   case ADD_VALUES:
1885   case ADD_ALL_VALUES:
1886     isInsert = PETSC_FALSE; break;
1887   default:
1888     SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1889   }
1890   if (sf && !isInsert) {
1891     ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr);
1892     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
1893     ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPI_SUM);CHKERRQ(ierr);
1894     ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr);
1895     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
1896   } else if (s && isInsert) {
1897     PetscInt gStart, pStart, pEnd, p;
1898 
1899     ierr = DMGetDefaultGlobalSection(dm, &gs);CHKERRQ(ierr);
1900     ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1901     ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr);
1902     ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr);
1903     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
1904     for (p = pStart; p < pEnd; ++p) {
1905       PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;
1906 
1907       ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
1908       ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr);
1909       ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
1910       ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr);
1911       ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr);
1912       ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr);
1913       /* Ignore off-process data and points with no global data */
1914       if (!gdof || goff < 0) continue;
1915       if (dof != gdof) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof);
1916       /* If no constraints are enforced in the global vector */
1917       if (!gcdof) {
1918         for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d];
1919       /* If constraints are enforced in the global vector */
1920       } else if (cdof == gcdof) {
1921         const PetscInt *cdofs;
1922         PetscInt        cind = 0;
1923 
1924         ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr);
1925         for (d = 0, e = 0; d < dof; ++d) {
1926           if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;}
1927           gArray[goff-gStart+e++] = lArray[off+d];
1928         }
1929       } else SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof);
1930     }
1931     ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr);
1932     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
1933   } else {
1934     ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr);
1935   }
1936   PetscFunctionReturn(0);
1937 }
1938 
1939 #undef __FUNCT__
1940 #define __FUNCT__ "DMLocalToGlobalEnd"
1941 /*@
1942     DMLocalToGlobalEnd - updates global vectors from local vectors
1943 
1944     Neighbor-wise Collective on DM
1945 
1946     Input Parameters:
1947 +   dm - the DM object
1948 .   l - the local vector
1949 .   mode - INSERT_VALUES or ADD_VALUES
1950 -   g - the global vector
1951 
1952 
1953     Level: beginner
1954 
1955 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()
1956 
1957 @*/
1958 PetscErrorCode  DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
1959 {
1960   PetscSF                 sf;
1961   PetscSection            s;
1962   DMLocalToGlobalHookLink link;
1963   PetscBool               isInsert;
1964   PetscErrorCode          ierr;
1965 
1966   PetscFunctionBegin;
1967   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1968   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1969   ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
1970   switch (mode) {
1971   case INSERT_VALUES:
1972   case INSERT_ALL_VALUES:
1973     isInsert = PETSC_TRUE; break;
1974   case ADD_VALUES:
1975   case ADD_ALL_VALUES:
1976     isInsert = PETSC_FALSE; break;
1977   default:
1978     SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1979   }
1980   if (sf && !isInsert) {
1981     const PetscScalar *lArray;
1982     PetscScalar       *gArray;
1983 
1984     ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr);
1985     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
1986     ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPI_SUM);CHKERRQ(ierr);
1987     ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr);
1988     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
1989   } else if (s && isInsert) {
1990   } else {
1991     ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr);
1992   }
1993   for (link=dm->ltoghook; link; link=link->next) {
1994     if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);}
1995   }
1996   PetscFunctionReturn(0);
1997 }
1998 
1999 #undef __FUNCT__
2000 #define __FUNCT__ "DMLocalToLocalBegin"
2001 /*@
2002    DMLocalToLocalBegin - Maps from a local vector (including ghost points
2003    that contain irrelevant values) to another local vector where the ghost
2004    points in the second are set correctly. Must be followed by DMLocalToLocalEnd().
2005 
2006    Neighbor-wise Collective on DM and Vec
2007 
2008    Input Parameters:
2009 +  dm - the DM object
2010 .  g - the original local vector
2011 -  mode - one of INSERT_VALUES or ADD_VALUES
2012 
2013    Output Parameter:
2014 .  l  - the local vector with correct ghost values
2015 
2016    Level: intermediate
2017 
2018    Notes:
2019    The local vectors used here need not be the same as those
2020    obtained from DMCreateLocalVector(), BUT they
2021    must have the same parallel data layout; they could, for example, be
2022    obtained with VecDuplicate() from the DM originating vectors.
2023 
2024 .keywords: DM, local-to-local, begin
2025 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2026 
2027 @*/
2028 PetscErrorCode  DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2029 {
2030   PetscErrorCode          ierr;
2031 
2032   PetscFunctionBegin;
2033   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2034   ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
2035   PetscFunctionReturn(0);
2036 }
2037 
2038 #undef __FUNCT__
2039 #define __FUNCT__ "DMLocalToLocalEnd"
2040 /*@
2041    DMLocalToLocalEnd - Maps from a local vector (including ghost points
2042    that contain irrelevant values) to another local vector where the ghost
2043    points in the second are set correctly. Must be preceded by DMLocalToLocalBegin().
2044 
2045    Neighbor-wise Collective on DM and Vec
2046 
2047    Input Parameters:
2048 +  da - the DM object
2049 .  g - the original local vector
2050 -  mode - one of INSERT_VALUES or ADD_VALUES
2051 
2052    Output Parameter:
2053 .  l  - the local vector with correct ghost values
2054 
2055    Level: intermediate
2056 
2057    Notes:
2058    The local vectors used here need not be the same as those
2059    obtained from DMCreateLocalVector(), BUT they
2060    must have the same parallel data layout; they could, for example, be
2061    obtained with VecDuplicate() from the DM originating vectors.
2062 
2063 .keywords: DM, local-to-local, end
2064 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2065 
2066 @*/
2067 PetscErrorCode  DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2068 {
2069   PetscErrorCode          ierr;
2070 
2071   PetscFunctionBegin;
2072   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2073   ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
2074   PetscFunctionReturn(0);
2075 }
2076 
2077 
2078 #undef __FUNCT__
2079 #define __FUNCT__ "DMCoarsen"
2080 /*@
2081     DMCoarsen - Coarsens a DM object
2082 
2083     Collective on DM
2084 
2085     Input Parameter:
2086 +   dm - the DM object
2087 -   comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
2088 
2089     Output Parameter:
2090 .   dmc - the coarsened DM
2091 
2092     Level: developer
2093 
2094 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2095 
2096 @*/
2097 PetscErrorCode  DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
2098 {
2099   PetscErrorCode    ierr;
2100   DMCoarsenHookLink link;
2101 
2102   PetscFunctionBegin;
2103   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2104   ierr                      = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr);
2105   (*dmc)->ops->creatematrix = dm->ops->creatematrix;
2106   ierr                      = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr);
2107   (*dmc)->ctx               = dm->ctx;
2108   (*dmc)->levelup           = dm->levelup;
2109   (*dmc)->leveldown         = dm->leveldown + 1;
2110   ierr                      = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr);
2111   for (link=dm->coarsenhook; link; link=link->next) {
2112     if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);}
2113   }
2114   PetscFunctionReturn(0);
2115 }
2116 
2117 #undef __FUNCT__
2118 #define __FUNCT__ "DMCoarsenHookAdd"
2119 /*@C
2120    DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
2121 
2122    Logically Collective
2123 
2124    Input Arguments:
2125 +  fine - nonlinear solver context on which to run a hook when restricting to a coarser level
2126 .  coarsenhook - function to run when setting up a coarser level
2127 .  restricthook - function to run to update data on coarser levels (once per SNESSolve())
2128 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2129 
2130    Calling sequence of coarsenhook:
2131 $    coarsenhook(DM fine,DM coarse,void *ctx);
2132 
2133 +  fine - fine level DM
2134 .  coarse - coarse level DM to restrict problem to
2135 -  ctx - optional user-defined function context
2136 
2137    Calling sequence for restricthook:
2138 $    restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx)
2139 
2140 +  fine - fine level DM
2141 .  mrestrict - matrix restricting a fine-level solution to the coarse grid
2142 .  rscale - scaling vector for restriction
2143 .  inject - matrix restricting by injection
2144 .  coarse - coarse level DM to update
2145 -  ctx - optional user-defined function context
2146 
2147    Level: advanced
2148 
2149    Notes:
2150    This function is only needed if auxiliary data needs to be set up on coarse grids.
2151 
2152    If this function is called multiple times, the hooks will be run in the order they are added.
2153 
2154    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2155    extract the finest level information from its context (instead of from the SNES).
2156 
2157    This function is currently not available from Fortran.
2158 
2159 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2160 @*/
2161 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
2162 {
2163   PetscErrorCode    ierr;
2164   DMCoarsenHookLink link,*p;
2165 
2166   PetscFunctionBegin;
2167   PetscValidHeaderSpecific(fine,DM_CLASSID,1);
2168   for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2169   ierr               = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&link);CHKERRQ(ierr);
2170   link->coarsenhook  = coarsenhook;
2171   link->restricthook = restricthook;
2172   link->ctx          = ctx;
2173   link->next         = NULL;
2174   *p                 = link;
2175   PetscFunctionReturn(0);
2176 }
2177 
2178 #undef __FUNCT__
2179 #define __FUNCT__ "DMRestrict"
2180 /*@
2181    DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd()
2182 
2183    Collective if any hooks are
2184 
2185    Input Arguments:
2186 +  fine - finer DM to use as a base
2187 .  restrct - restriction matrix, apply using MatRestrict()
2188 .  inject - injection matrix, also use MatRestrict()
2189 -  coarse - coarer DM to update
2190 
2191    Level: developer
2192 
2193 .seealso: DMCoarsenHookAdd(), MatRestrict()
2194 @*/
2195 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse)
2196 {
2197   PetscErrorCode    ierr;
2198   DMCoarsenHookLink link;
2199 
2200   PetscFunctionBegin;
2201   for (link=fine->coarsenhook; link; link=link->next) {
2202     if (link->restricthook) {
2203       ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr);
2204     }
2205   }
2206   PetscFunctionReturn(0);
2207 }
2208 
2209 #undef __FUNCT__
2210 #define __FUNCT__ "DMSubDomainHookAdd"
2211 /*@C
2212    DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
2213 
2214    Logically Collective
2215 
2216    Input Arguments:
2217 +  global - global DM
2218 .  ddhook - function to run to pass data to the decomposition DM upon its creation
2219 .  restricthook - function to run to update data on block solve (at the beginning of the block solve)
2220 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2221 
2222 
2223    Calling sequence for ddhook:
2224 $    ddhook(DM global,DM block,void *ctx)
2225 
2226 +  global - global DM
2227 .  block  - block DM
2228 -  ctx - optional user-defined function context
2229 
2230    Calling sequence for restricthook:
2231 $    restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx)
2232 
2233 +  global - global DM
2234 .  out    - scatter to the outer (with ghost and overlap points) block vector
2235 .  in     - scatter to block vector values only owned locally
2236 .  block  - block DM
2237 -  ctx - optional user-defined function context
2238 
2239    Level: advanced
2240 
2241    Notes:
2242    This function is only needed if auxiliary data needs to be set up on subdomain DMs.
2243 
2244    If this function is called multiple times, the hooks will be run in the order they are added.
2245 
2246    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2247    extract the global information from its context (instead of from the SNES).
2248 
2249    This function is currently not available from Fortran.
2250 
2251 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2252 @*/
2253 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
2254 {
2255   PetscErrorCode      ierr;
2256   DMSubDomainHookLink link,*p;
2257 
2258   PetscFunctionBegin;
2259   PetscValidHeaderSpecific(global,DM_CLASSID,1);
2260   for (p=&global->subdomainhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2261   ierr               = PetscMalloc(sizeof(struct _DMSubDomainHookLink),&link);CHKERRQ(ierr);
2262   link->restricthook = restricthook;
2263   link->ddhook       = ddhook;
2264   link->ctx          = ctx;
2265   link->next         = NULL;
2266   *p                 = link;
2267   PetscFunctionReturn(0);
2268 }
2269 
2270 #undef __FUNCT__
2271 #define __FUNCT__ "DMSubDomainRestrict"
2272 /*@
2273    DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd()
2274 
2275    Collective if any hooks are
2276 
2277    Input Arguments:
2278 +  fine - finer DM to use as a base
2279 .  oscatter - scatter from domain global vector filling subdomain global vector with overlap
2280 .  gscatter - scatter from domain global vector filling subdomain local vector with ghosts
2281 -  coarse - coarer DM to update
2282 
2283    Level: developer
2284 
2285 .seealso: DMCoarsenHookAdd(), MatRestrict()
2286 @*/
2287 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm)
2288 {
2289   PetscErrorCode      ierr;
2290   DMSubDomainHookLink link;
2291 
2292   PetscFunctionBegin;
2293   for (link=global->subdomainhook; link; link=link->next) {
2294     if (link->restricthook) {
2295       ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr);
2296     }
2297   }
2298   PetscFunctionReturn(0);
2299 }
2300 
2301 #undef __FUNCT__
2302 #define __FUNCT__ "DMGetCoarsenLevel"
2303 /*@
2304     DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM.
2305 
2306     Not Collective
2307 
2308     Input Parameter:
2309 .   dm - the DM object
2310 
2311     Output Parameter:
2312 .   level - number of coarsenings
2313 
2314     Level: developer
2315 
2316 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2317 
2318 @*/
2319 PetscErrorCode  DMGetCoarsenLevel(DM dm,PetscInt *level)
2320 {
2321   PetscFunctionBegin;
2322   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2323   *level = dm->leveldown;
2324   PetscFunctionReturn(0);
2325 }
2326 
2327 
2328 
2329 #undef __FUNCT__
2330 #define __FUNCT__ "DMRefineHierarchy"
2331 /*@C
2332     DMRefineHierarchy - Refines a DM object, all levels at once
2333 
2334     Collective on DM
2335 
2336     Input Parameter:
2337 +   dm - the DM object
2338 -   nlevels - the number of levels of refinement
2339 
2340     Output Parameter:
2341 .   dmf - the refined DM hierarchy
2342 
2343     Level: developer
2344 
2345 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2346 
2347 @*/
2348 PetscErrorCode  DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
2349 {
2350   PetscErrorCode ierr;
2351 
2352   PetscFunctionBegin;
2353   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2354   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2355   if (nlevels == 0) PetscFunctionReturn(0);
2356   if (dm->ops->refinehierarchy) {
2357     ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr);
2358   } else if (dm->ops->refine) {
2359     PetscInt i;
2360 
2361     ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr);
2362     for (i=1; i<nlevels; i++) {
2363       ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr);
2364     }
2365   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
2366   PetscFunctionReturn(0);
2367 }
2368 
2369 #undef __FUNCT__
2370 #define __FUNCT__ "DMCoarsenHierarchy"
2371 /*@C
2372     DMCoarsenHierarchy - Coarsens a DM object, all levels at once
2373 
2374     Collective on DM
2375 
2376     Input Parameter:
2377 +   dm - the DM object
2378 -   nlevels - the number of levels of coarsening
2379 
2380     Output Parameter:
2381 .   dmc - the coarsened DM hierarchy
2382 
2383     Level: developer
2384 
2385 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2386 
2387 @*/
2388 PetscErrorCode  DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
2389 {
2390   PetscErrorCode ierr;
2391 
2392   PetscFunctionBegin;
2393   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2394   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2395   if (nlevels == 0) PetscFunctionReturn(0);
2396   PetscValidPointer(dmc,3);
2397   if (dm->ops->coarsenhierarchy) {
2398     ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr);
2399   } else if (dm->ops->coarsen) {
2400     PetscInt i;
2401 
2402     ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr);
2403     for (i=1; i<nlevels; i++) {
2404       ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr);
2405     }
2406   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
2407   PetscFunctionReturn(0);
2408 }
2409 
2410 #undef __FUNCT__
2411 #define __FUNCT__ "DMCreateAggregates"
2412 /*@
2413    DMCreateAggregates - Gets the aggregates that map between
2414    grids associated with two DMs.
2415 
2416    Collective on DM
2417 
2418    Input Parameters:
2419 +  dmc - the coarse grid DM
2420 -  dmf - the fine grid DM
2421 
2422    Output Parameters:
2423 .  rest - the restriction matrix (transpose of the projection matrix)
2424 
2425    Level: intermediate
2426 
2427 .keywords: interpolation, restriction, multigrid
2428 
2429 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation()
2430 @*/
2431 PetscErrorCode  DMCreateAggregates(DM dmc, DM dmf, Mat *rest)
2432 {
2433   PetscErrorCode ierr;
2434 
2435   PetscFunctionBegin;
2436   PetscValidHeaderSpecific(dmc,DM_CLASSID,1);
2437   PetscValidHeaderSpecific(dmf,DM_CLASSID,2);
2438   ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr);
2439   PetscFunctionReturn(0);
2440 }
2441 
2442 #undef __FUNCT__
2443 #define __FUNCT__ "DMSetApplicationContextDestroy"
2444 /*@C
2445     DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed
2446 
2447     Not Collective
2448 
2449     Input Parameters:
2450 +   dm - the DM object
2451 -   destroy - the destroy function
2452 
2453     Level: intermediate
2454 
2455 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2456 
2457 @*/
2458 PetscErrorCode  DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**))
2459 {
2460   PetscFunctionBegin;
2461   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2462   dm->ctxdestroy = destroy;
2463   PetscFunctionReturn(0);
2464 }
2465 
2466 #undef __FUNCT__
2467 #define __FUNCT__ "DMSetApplicationContext"
2468 /*@
2469     DMSetApplicationContext - Set a user context into a DM object
2470 
2471     Not Collective
2472 
2473     Input Parameters:
2474 +   dm - the DM object
2475 -   ctx - the user context
2476 
2477     Level: intermediate
2478 
2479 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2480 
2481 @*/
2482 PetscErrorCode  DMSetApplicationContext(DM dm,void *ctx)
2483 {
2484   PetscFunctionBegin;
2485   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2486   dm->ctx = ctx;
2487   PetscFunctionReturn(0);
2488 }
2489 
2490 #undef __FUNCT__
2491 #define __FUNCT__ "DMGetApplicationContext"
2492 /*@
2493     DMGetApplicationContext - Gets a user context from a DM object
2494 
2495     Not Collective
2496 
2497     Input Parameter:
2498 .   dm - the DM object
2499 
2500     Output Parameter:
2501 .   ctx - the user context
2502 
2503     Level: intermediate
2504 
2505 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2506 
2507 @*/
2508 PetscErrorCode  DMGetApplicationContext(DM dm,void *ctx)
2509 {
2510   PetscFunctionBegin;
2511   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2512   *(void**)ctx = dm->ctx;
2513   PetscFunctionReturn(0);
2514 }
2515 
2516 #undef __FUNCT__
2517 #define __FUNCT__ "DMSetVariableBounds"
2518 /*@C
2519     DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI.
2520 
2521     Logically Collective on DM
2522 
2523     Input Parameter:
2524 +   dm - the DM object
2525 -   f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set)
2526 
2527     Level: intermediate
2528 
2529 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(),
2530          DMSetJacobian()
2531 
2532 @*/
2533 PetscErrorCode  DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
2534 {
2535   PetscFunctionBegin;
2536   dm->ops->computevariablebounds = f;
2537   PetscFunctionReturn(0);
2538 }
2539 
2540 #undef __FUNCT__
2541 #define __FUNCT__ "DMHasVariableBounds"
2542 /*@
2543     DMHasVariableBounds - does the DM object have a variable bounds function?
2544 
2545     Not Collective
2546 
2547     Input Parameter:
2548 .   dm - the DM object to destroy
2549 
2550     Output Parameter:
2551 .   flg - PETSC_TRUE if the variable bounds function exists
2552 
2553     Level: developer
2554 
2555 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2556 
2557 @*/
2558 PetscErrorCode  DMHasVariableBounds(DM dm,PetscBool  *flg)
2559 {
2560   PetscFunctionBegin;
2561   *flg =  (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
2562   PetscFunctionReturn(0);
2563 }
2564 
2565 #undef __FUNCT__
2566 #define __FUNCT__ "DMComputeVariableBounds"
2567 /*@C
2568     DMComputeVariableBounds - compute variable bounds used by SNESVI.
2569 
2570     Logically Collective on DM
2571 
2572     Input Parameters:
2573 .   dm - the DM object
2574 
2575     Output parameters:
2576 +   xl - lower bound
2577 -   xu - upper bound
2578 
2579     Level: advanced
2580 
2581     Notes: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()
2582 
2583 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2584 
2585 @*/
2586 PetscErrorCode  DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
2587 {
2588   PetscErrorCode ierr;
2589 
2590   PetscFunctionBegin;
2591   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
2592   PetscValidHeaderSpecific(xu,VEC_CLASSID,2);
2593   if (dm->ops->computevariablebounds) {
2594     ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr);
2595   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds.");
2596   PetscFunctionReturn(0);
2597 }
2598 
2599 #undef __FUNCT__
2600 #define __FUNCT__ "DMHasColoring"
2601 /*@
2602     DMHasColoring - does the DM object have a method of providing a coloring?
2603 
2604     Not Collective
2605 
2606     Input Parameter:
2607 .   dm - the DM object
2608 
2609     Output Parameter:
2610 .   flg - PETSC_TRUE if the DM has facilities for DMCreateColoring().
2611 
2612     Level: developer
2613 
2614 .seealso DMHasFunction(), DMCreateColoring()
2615 
2616 @*/
2617 PetscErrorCode  DMHasColoring(DM dm,PetscBool  *flg)
2618 {
2619   PetscFunctionBegin;
2620   *flg =  (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
2621   PetscFunctionReturn(0);
2622 }
2623 
2624 #undef  __FUNCT__
2625 #define __FUNCT__ "DMSetVec"
2626 /*@C
2627     DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear.
2628 
2629     Collective on DM
2630 
2631     Input Parameter:
2632 +   dm - the DM object
2633 -   x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems.
2634 
2635     Level: developer
2636 
2637 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2638 
2639 @*/
2640 PetscErrorCode  DMSetVec(DM dm,Vec x)
2641 {
2642   PetscErrorCode ierr;
2643 
2644   PetscFunctionBegin;
2645   if (x) {
2646     if (!dm->x) {
2647       ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr);
2648     }
2649     ierr = VecCopy(x,dm->x);CHKERRQ(ierr);
2650   } else if (dm->x) {
2651     ierr = VecDestroy(&dm->x);CHKERRQ(ierr);
2652   }
2653   PetscFunctionReturn(0);
2654 }
2655 
2656 PetscFunctionList DMList              = NULL;
2657 PetscBool         DMRegisterAllCalled = PETSC_FALSE;
2658 
2659 #undef __FUNCT__
2660 #define __FUNCT__ "DMSetType"
2661 /*@C
2662   DMSetType - Builds a DM, for a particular DM implementation.
2663 
2664   Collective on DM
2665 
2666   Input Parameters:
2667 + dm     - The DM object
2668 - method - The name of the DM type
2669 
2670   Options Database Key:
2671 . -dm_type <type> - Sets the DM type; use -help for a list of available types
2672 
2673   Notes:
2674   See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).
2675 
2676   Level: intermediate
2677 
2678 .keywords: DM, set, type
2679 .seealso: DMGetType(), DMCreate()
2680 @*/
2681 PetscErrorCode  DMSetType(DM dm, DMType method)
2682 {
2683   PetscErrorCode (*r)(DM);
2684   PetscBool      match;
2685   PetscErrorCode ierr;
2686 
2687   PetscFunctionBegin;
2688   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
2689   ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr);
2690   if (match) PetscFunctionReturn(0);
2691 
2692   ierr = DMRegisterAll();CHKERRQ(ierr);
2693   ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr);
2694   if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
2695 
2696   if (dm->ops->destroy) {
2697     ierr             = (*dm->ops->destroy)(dm);CHKERRQ(ierr);
2698     dm->ops->destroy = NULL;
2699   }
2700   ierr = (*r)(dm);CHKERRQ(ierr);
2701   ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr);
2702   PetscFunctionReturn(0);
2703 }
2704 
2705 #undef __FUNCT__
2706 #define __FUNCT__ "DMGetType"
2707 /*@C
2708   DMGetType - Gets the DM type name (as a string) from the DM.
2709 
2710   Not Collective
2711 
2712   Input Parameter:
2713 . dm  - The DM
2714 
2715   Output Parameter:
2716 . type - The DM type name
2717 
2718   Level: intermediate
2719 
2720 .keywords: DM, get, type, name
2721 .seealso: DMSetType(), DMCreate()
2722 @*/
2723 PetscErrorCode  DMGetType(DM dm, DMType *type)
2724 {
2725   PetscErrorCode ierr;
2726 
2727   PetscFunctionBegin;
2728   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
2729   PetscValidPointer(type,2);
2730   ierr = DMRegisterAll();CHKERRQ(ierr);
2731   *type = ((PetscObject)dm)->type_name;
2732   PetscFunctionReturn(0);
2733 }
2734 
2735 #undef __FUNCT__
2736 #define __FUNCT__ "DMConvert"
2737 /*@C
2738   DMConvert - Converts a DM to another DM, either of the same or different type.
2739 
2740   Collective on DM
2741 
2742   Input Parameters:
2743 + dm - the DM
2744 - newtype - new DM type (use "same" for the same type)
2745 
2746   Output Parameter:
2747 . M - pointer to new DM
2748 
2749   Notes:
2750   Cannot be used to convert a sequential DM to parallel or parallel to sequential,
2751   the MPI communicator of the generated DM is always the same as the communicator
2752   of the input DM.
2753 
2754   Level: intermediate
2755 
2756 .seealso: DMCreate()
2757 @*/
2758 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
2759 {
2760   DM             B;
2761   char           convname[256];
2762   PetscBool      sametype, issame;
2763   PetscErrorCode ierr;
2764 
2765   PetscFunctionBegin;
2766   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2767   PetscValidType(dm,1);
2768   PetscValidPointer(M,3);
2769   ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr);
2770   ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr);
2771   {
2772     PetscErrorCode (*conv)(DM, DMType, DM*) = NULL;
2773 
2774     /*
2775        Order of precedence:
2776        1) See if a specialized converter is known to the current DM.
2777        2) See if a specialized converter is known to the desired DM class.
2778        3) See if a good general converter is registered for the desired class
2779        4) See if a good general converter is known for the current matrix.
2780        5) Use a really basic converter.
2781     */
2782 
2783     /* 1) See if a specialized converter is known to the current DM and the desired class */
2784     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
2785     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
2786     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
2787     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
2788     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
2789     ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr);
2790     if (conv) goto foundconv;
2791 
2792     /* 2)  See if a specialized converter is known to the desired DM class. */
2793     ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr);
2794     ierr = DMSetType(B, newtype);CHKERRQ(ierr);
2795     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
2796     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
2797     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
2798     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
2799     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
2800     ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr);
2801     if (conv) {
2802       ierr = DMDestroy(&B);CHKERRQ(ierr);
2803       goto foundconv;
2804     }
2805 
2806 #if 0
2807     /* 3) See if a good general converter is registered for the desired class */
2808     conv = B->ops->convertfrom;
2809     ierr = DMDestroy(&B);CHKERRQ(ierr);
2810     if (conv) goto foundconv;
2811 
2812     /* 4) See if a good general converter is known for the current matrix */
2813     if (dm->ops->convert) {
2814       conv = dm->ops->convert;
2815     }
2816     if (conv) goto foundconv;
2817 #endif
2818 
2819     /* 5) Use a really basic converter. */
2820     SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);
2821 
2822 foundconv:
2823     ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
2824     ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr);
2825     ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
2826   }
2827   ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr);
2828   PetscFunctionReturn(0);
2829 }
2830 
2831 /*--------------------------------------------------------------------------------------------------------------------*/
2832 
2833 #undef __FUNCT__
2834 #define __FUNCT__ "DMRegister"
2835 /*@C
2836   DMRegister -  Adds a new DM component implementation
2837 
2838   Not Collective
2839 
2840   Input Parameters:
2841 + name        - The name of a new user-defined creation routine
2842 - create_func - The creation routine itself
2843 
2844   Notes:
2845   DMRegister() may be called multiple times to add several user-defined DMs
2846 
2847 
2848   Sample usage:
2849 .vb
2850     DMRegister("my_da", MyDMCreate);
2851 .ve
2852 
2853   Then, your DM type can be chosen with the procedural interface via
2854 .vb
2855     DMCreate(MPI_Comm, DM *);
2856     DMSetType(DM,"my_da");
2857 .ve
2858    or at runtime via the option
2859 .vb
2860     -da_type my_da
2861 .ve
2862 
2863   Level: advanced
2864 
2865 .keywords: DM, register
2866 .seealso: DMRegisterAll(), DMRegisterDestroy()
2867 
2868 @*/
2869 PetscErrorCode  DMRegister(const char sname[],PetscErrorCode (*function)(DM))
2870 {
2871   PetscErrorCode ierr;
2872 
2873   PetscFunctionBegin;
2874   ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr);
2875   PetscFunctionReturn(0);
2876 }
2877 
2878 #undef __FUNCT__
2879 #define __FUNCT__ "DMLoad"
2880 /*@C
2881   DMLoad - Loads a DM that has been stored in binary  with DMView().
2882 
2883   Collective on PetscViewer
2884 
2885   Input Parameters:
2886 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
2887            some related function before a call to DMLoad().
2888 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
2889            HDF5 file viewer, obtained from PetscViewerHDF5Open()
2890 
2891    Level: intermediate
2892 
2893   Notes:
2894    The type is determined by the data in the file, any type set into the DM before this call is ignored.
2895 
2896   Notes for advanced users:
2897   Most users should not need to know the details of the binary storage
2898   format, since DMLoad() and DMView() completely hide these details.
2899   But for anyone who's interested, the standard binary matrix storage
2900   format is
2901 .vb
2902      has not yet been determined
2903 .ve
2904 
2905 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad()
2906 @*/
2907 PetscErrorCode  DMLoad(DM newdm, PetscViewer viewer)
2908 {
2909   PetscBool      isbinary, ishdf5;
2910   PetscErrorCode ierr;
2911 
2912   PetscFunctionBegin;
2913   PetscValidHeaderSpecific(newdm,DM_CLASSID,1);
2914   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
2915   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
2916   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
2917   if (isbinary) {
2918     PetscInt classid;
2919     char     type[256];
2920 
2921     ierr = PetscViewerBinaryRead(viewer,&classid,1,PETSC_INT);CHKERRQ(ierr);
2922     if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid);
2923     ierr = PetscViewerBinaryRead(viewer,type,256,PETSC_CHAR);CHKERRQ(ierr);
2924     ierr = DMSetType(newdm, type);CHKERRQ(ierr);
2925     if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);}
2926   } else if (ishdf5) {
2927     if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);}
2928   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
2929   PetscFunctionReturn(0);
2930 }
2931 
2932 /******************************** FEM Support **********************************/
2933 
2934 #undef __FUNCT__
2935 #define __FUNCT__ "DMPrintCellVector"
2936 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
2937 {
2938   PetscInt       f;
2939   PetscErrorCode ierr;
2940 
2941   PetscFunctionBegin;
2942   ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
2943   for (f = 0; f < len; ++f) {
2944     ierr = PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr);
2945   }
2946   PetscFunctionReturn(0);
2947 }
2948 
2949 #undef __FUNCT__
2950 #define __FUNCT__ "DMPrintCellMatrix"
2951 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
2952 {
2953   PetscInt       f, g;
2954   PetscErrorCode ierr;
2955 
2956   PetscFunctionBegin;
2957   ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
2958   for (f = 0; f < rows; ++f) {
2959     ierr = PetscPrintf(PETSC_COMM_SELF, "  |");CHKERRQ(ierr);
2960     for (g = 0; g < cols; ++g) {
2961       ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr);
2962     }
2963     ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr);
2964   }
2965   PetscFunctionReturn(0);
2966 }
2967 
2968 #undef __FUNCT__
2969 #define __FUNCT__ "DMPrintLocalVec"
2970 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
2971 {
2972   PetscMPIInt    rank, numProcs;
2973   PetscInt       p;
2974   PetscErrorCode ierr;
2975 
2976   PetscFunctionBegin;
2977   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr);
2978   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr);
2979   ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "%s:\n", name);CHKERRQ(ierr);
2980   for (p = 0; p < numProcs; ++p) {
2981     if (p == rank) {
2982       Vec x;
2983 
2984       ierr = VecDuplicate(X, &x);CHKERRQ(ierr);
2985       ierr = VecCopy(X, x);CHKERRQ(ierr);
2986       ierr = VecChop(x, tol);CHKERRQ(ierr);
2987       ierr = VecView(x, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2988       ierr = VecDestroy(&x);CHKERRQ(ierr);
2989       ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2990     }
2991     ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr);
2992   }
2993   PetscFunctionReturn(0);
2994 }
2995 
2996 #undef __FUNCT__
2997 #define __FUNCT__ "DMGetDefaultSection"
2998 /*@
2999   DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM.
3000 
3001   Input Parameter:
3002 . dm - The DM
3003 
3004   Output Parameter:
3005 . section - The PetscSection
3006 
3007   Level: intermediate
3008 
3009   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3010 
3011 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
3012 @*/
3013 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section)
3014 {
3015   PetscErrorCode ierr;
3016 
3017   PetscFunctionBegin;
3018   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3019   PetscValidPointer(section, 2);
3020   if (!dm->defaultSection && dm->ops->createdefaultsection) {
3021     ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr);
3022     ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, "dm_", "-petscsection_view");CHKERRQ(ierr);
3023   }
3024   *section = dm->defaultSection;
3025   PetscFunctionReturn(0);
3026 }
3027 
3028 #undef __FUNCT__
3029 #define __FUNCT__ "DMSetDefaultSection"
3030 /*@
3031   DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM.
3032 
3033   Input Parameters:
3034 + dm - The DM
3035 - section - The PetscSection
3036 
3037   Level: intermediate
3038 
3039   Note: Any existing Section will be destroyed
3040 
3041 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
3042 @*/
3043 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section)
3044 {
3045   PetscInt       numFields;
3046   PetscInt       f;
3047   PetscErrorCode ierr;
3048 
3049   PetscFunctionBegin;
3050   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3051   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
3052   ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
3053   ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr);
3054   dm->defaultSection = section;
3055   ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);
3056   if (numFields) {
3057     ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr);
3058     for (f = 0; f < numFields; ++f) {
3059       PetscObject disc;
3060       const char *name;
3061 
3062       ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr);
3063       ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr);
3064       ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr);
3065     }
3066   }
3067   /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */
3068   ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr);
3069   PetscFunctionReturn(0);
3070 }
3071 
3072 #undef __FUNCT__
3073 #define __FUNCT__ "DMGetDefaultConstraints"
3074 /*@
3075   DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation.
3076 
3077   not collective
3078 
3079   Input Parameter:
3080 . dm - The DM
3081 
3082   Output Parameter:
3083 + 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.
3084 - 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.
3085 
3086   Level: advanced
3087 
3088   Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat.
3089 
3090 .seealso: DMSetDefaultConstraints()
3091 @*/
3092 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat)
3093 {
3094   PetscErrorCode ierr;
3095 
3096   PetscFunctionBegin;
3097   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3098   if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);}
3099   if (section) {*section = dm->defaultConstraintSection;}
3100   if (mat) {*mat = dm->defaultConstraintMat;}
3101   PetscFunctionReturn(0);
3102 }
3103 
3104 #undef __FUNCT__
3105 #define __FUNCT__ "DMSetDefaultConstraints"
3106 /*@
3107   DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation.
3108 
3109   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().
3110 
3111   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.
3112 
3113   collective on dm
3114 
3115   Input Parameters:
3116 + dm - The DM
3117 + 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).
3118 - 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).
3119 
3120   Level: advanced
3121 
3122   Note: This increments the references of the PetscSection and the Mat, so they user can destroy them
3123 
3124 .seealso: DMGetDefaultConstraints()
3125 @*/
3126 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat)
3127 {
3128   PetscMPIInt result;
3129   PetscErrorCode ierr;
3130 
3131   PetscFunctionBegin;
3132   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3133   if (section) {
3134     PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
3135     ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr);
3136     if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator");
3137   }
3138   if (mat) {
3139     PetscValidHeaderSpecific(mat,MAT_CLASSID,3);
3140     ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr);
3141     if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator");
3142   }
3143   ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
3144   ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr);
3145   dm->defaultConstraintSection = section;
3146   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
3147   ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr);
3148   dm->defaultConstraintMat = mat;
3149   PetscFunctionReturn(0);
3150 }
3151 
3152 #ifdef PETSC_USE_DEBUG
3153 #undef __FUNCT__
3154 #define __FUNCT__ "DMDefaultSectionCheckConsistency_Internal"
3155 /*
3156   DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections.
3157 
3158   Input Parameters:
3159 + dm - The DM
3160 . localSection - PetscSection describing the local data layout
3161 - globalSection - PetscSection describing the global data layout
3162 
3163   Level: intermediate
3164 
3165 .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3166 */
3167 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
3168 {
3169   MPI_Comm        comm;
3170   PetscLayout     layout;
3171   const PetscInt *ranges;
3172   PetscInt        pStart, pEnd, p, nroots;
3173   PetscMPIInt     size, rank;
3174   PetscBool       valid = PETSC_TRUE, gvalid;
3175   PetscErrorCode  ierr;
3176 
3177   PetscFunctionBegin;
3178   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
3179   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3180   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
3181   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3182   ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr);
3183   ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr);
3184   ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
3185   ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
3186   ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr);
3187   ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
3188   ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
3189   for (p = pStart; p < pEnd; ++p) {
3190     PetscInt       dof, cdof, off, gdof, gcdof, goff, gsize, d;
3191 
3192     ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr);
3193     ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr);
3194     ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr);
3195     ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3196     ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3197     ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr);
3198     if (!gdof) continue; /* Censored point */
3199     if ((gdof < 0 ? -(gdof+1) : gdof) != dof) {ierr = PetscSynchronizedPrintf(comm, "[%d]Global dof %d for point %d not equal to local dof %d\n", rank, gdof, p, dof);CHKERRQ(ierr); valid = PETSC_FALSE;}
3200     if (gcdof && (gcdof != cdof)) {ierr = PetscSynchronizedPrintf(comm, "[%d]Global constraints %d for point %d not equal to local constraints %d\n", rank, gcdof, p, cdof);CHKERRQ(ierr); valid = PETSC_FALSE;}
3201     if (gdof < 0) {
3202       gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3203       for (d = 0; d < gsize; ++d) {
3204         PetscInt offset = -(goff+1) + d, r;
3205 
3206         ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr);
3207         if (r < 0) r = -(r+2);
3208         if ((r < 0) || (r >= size)) {ierr = PetscSynchronizedPrintf(comm, "[%d]Point %d mapped to invalid process %d (%d, %d)\n", rank, p, r, gdof, goff);CHKERRQ(ierr); valid = PETSC_FALSE;break;}
3209       }
3210     }
3211   }
3212   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
3213   ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
3214   ierr = MPI_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr);
3215   if (!gvalid) {
3216     ierr = DMView(dm, NULL);CHKERRQ(ierr);
3217     SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
3218   }
3219   PetscFunctionReturn(0);
3220 }
3221 #endif
3222 
3223 #undef __FUNCT__
3224 #define __FUNCT__ "DMGetDefaultGlobalSection"
3225 /*@
3226   DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM.
3227 
3228   Collective on DM
3229 
3230   Input Parameter:
3231 . dm - The DM
3232 
3233   Output Parameter:
3234 . section - The PetscSection
3235 
3236   Level: intermediate
3237 
3238   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3239 
3240 .seealso: DMSetDefaultSection(), DMGetDefaultSection()
3241 @*/
3242 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section)
3243 {
3244   PetscErrorCode ierr;
3245 
3246   PetscFunctionBegin;
3247   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3248   PetscValidPointer(section, 2);
3249   if (!dm->defaultGlobalSection) {
3250     PetscSection s;
3251 
3252     ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
3253     if (!s)  SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
3254     if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection");
3255     ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr);
3256     ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr);
3257     ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr);
3258   }
3259   *section = dm->defaultGlobalSection;
3260   PetscFunctionReturn(0);
3261 }
3262 
3263 #undef __FUNCT__
3264 #define __FUNCT__ "DMSetDefaultGlobalSection"
3265 /*@
3266   DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM.
3267 
3268   Input Parameters:
3269 + dm - The DM
3270 - section - The PetscSection, or NULL
3271 
3272   Level: intermediate
3273 
3274   Note: Any existing Section will be destroyed
3275 
3276 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection()
3277 @*/
3278 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section)
3279 {
3280   PetscErrorCode ierr;
3281 
3282   PetscFunctionBegin;
3283   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3284   if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
3285   ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
3286   ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr);
3287   dm->defaultGlobalSection = section;
3288 #ifdef PETSC_USE_DEBUG
3289   if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);}
3290 #endif
3291   PetscFunctionReturn(0);
3292 }
3293 
3294 #undef __FUNCT__
3295 #define __FUNCT__ "DMGetDefaultSF"
3296 /*@
3297   DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set,
3298   it is created from the default PetscSection layouts in the DM.
3299 
3300   Input Parameter:
3301 . dm - The DM
3302 
3303   Output Parameter:
3304 . sf - The PetscSF
3305 
3306   Level: intermediate
3307 
3308   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3309 
3310 .seealso: DMSetDefaultSF(), DMCreateDefaultSF()
3311 @*/
3312 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf)
3313 {
3314   PetscInt       nroots;
3315   PetscErrorCode ierr;
3316 
3317   PetscFunctionBegin;
3318   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3319   PetscValidPointer(sf, 2);
3320   ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
3321   if (nroots < 0) {
3322     PetscSection section, gSection;
3323 
3324     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
3325     if (section) {
3326       ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr);
3327       ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr);
3328     } else {
3329       *sf = NULL;
3330       PetscFunctionReturn(0);
3331     }
3332   }
3333   *sf = dm->defaultSF;
3334   PetscFunctionReturn(0);
3335 }
3336 
3337 #undef __FUNCT__
3338 #define __FUNCT__ "DMSetDefaultSF"
3339 /*@
3340   DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM
3341 
3342   Input Parameters:
3343 + dm - The DM
3344 - sf - The PetscSF
3345 
3346   Level: intermediate
3347 
3348   Note: Any previous SF is destroyed
3349 
3350 .seealso: DMGetDefaultSF(), DMCreateDefaultSF()
3351 @*/
3352 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf)
3353 {
3354   PetscErrorCode ierr;
3355 
3356   PetscFunctionBegin;
3357   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3358   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
3359   ierr          = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr);
3360   dm->defaultSF = sf;
3361   PetscFunctionReturn(0);
3362 }
3363 
3364 #undef __FUNCT__
3365 #define __FUNCT__ "DMCreateDefaultSF"
3366 /*@C
3367   DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections
3368   describing the data layout.
3369 
3370   Input Parameters:
3371 + dm - The DM
3372 . localSection - PetscSection describing the local data layout
3373 - globalSection - PetscSection describing the global data layout
3374 
3375   Level: intermediate
3376 
3377 .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3378 @*/
3379 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection)
3380 {
3381   MPI_Comm       comm;
3382   PetscLayout    layout;
3383   const PetscInt *ranges;
3384   PetscInt       *local;
3385   PetscSFNode    *remote;
3386   PetscInt       pStart, pEnd, p, nroots, nleaves = 0, l;
3387   PetscMPIInt    size, rank;
3388   PetscErrorCode ierr;
3389 
3390   PetscFunctionBegin;
3391   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
3392   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3393   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
3394   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3395   ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr);
3396   ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr);
3397   ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
3398   ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
3399   ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr);
3400   ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
3401   ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
3402   for (p = pStart; p < pEnd; ++p) {
3403     PetscInt gdof, gcdof;
3404 
3405     ierr     = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3406     ierr     = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3407     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));
3408     nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3409   }
3410   ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr);
3411   ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr);
3412   for (p = pStart, l = 0; p < pEnd; ++p) {
3413     const PetscInt *cind;
3414     PetscInt       dof, cdof, off, gdof, gcdof, goff, gsize, d, c;
3415 
3416     ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr);
3417     ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr);
3418     ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr);
3419     ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr);
3420     ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3421     ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3422     ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr);
3423     if (!gdof) continue; /* Censored point */
3424     gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3425     if (gsize != dof-cdof) {
3426       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);
3427       cdof = 0; /* Ignore constraints */
3428     }
3429     for (d = 0, c = 0; d < dof; ++d) {
3430       if ((c < cdof) && (cind[c] == d)) {++c; continue;}
3431       local[l+d-c] = off+d;
3432     }
3433     if (gdof < 0) {
3434       for (d = 0; d < gsize; ++d, ++l) {
3435         PetscInt offset = -(goff+1) + d, r;
3436 
3437         ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr);
3438         if (r < 0) r = -(r+2);
3439         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);
3440         remote[l].rank  = r;
3441         remote[l].index = offset - ranges[r];
3442       }
3443     } else {
3444       for (d = 0; d < gsize; ++d, ++l) {
3445         remote[l].rank  = rank;
3446         remote[l].index = goff+d - ranges[rank];
3447       }
3448     }
3449   }
3450   if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves);
3451   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
3452   ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr);
3453   PetscFunctionReturn(0);
3454 }
3455 
3456 #undef __FUNCT__
3457 #define __FUNCT__ "DMGetPointSF"
3458 /*@
3459   DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM.
3460 
3461   Input Parameter:
3462 . dm - The DM
3463 
3464   Output Parameter:
3465 . sf - The PetscSF
3466 
3467   Level: intermediate
3468 
3469   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3470 
3471 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3472 @*/
3473 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
3474 {
3475   PetscFunctionBegin;
3476   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3477   PetscValidPointer(sf, 2);
3478   *sf = dm->sf;
3479   PetscFunctionReturn(0);
3480 }
3481 
3482 #undef __FUNCT__
3483 #define __FUNCT__ "DMSetPointSF"
3484 /*@
3485   DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM.
3486 
3487   Input Parameters:
3488 + dm - The DM
3489 - sf - The PetscSF
3490 
3491   Level: intermediate
3492 
3493 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3494 @*/
3495 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
3496 {
3497   PetscErrorCode ierr;
3498 
3499   PetscFunctionBegin;
3500   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3501   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
3502   ierr   = PetscSFDestroy(&dm->sf);CHKERRQ(ierr);
3503   ierr   = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr);
3504   dm->sf = sf;
3505   PetscFunctionReturn(0);
3506 }
3507 
3508 #undef __FUNCT__
3509 #define __FUNCT__ "DMGetDS"
3510 /*@
3511   DMGetDS - Get the PetscDS
3512 
3513   Input Parameter:
3514 . dm - The DM
3515 
3516   Output Parameter:
3517 . prob - The PetscDS
3518 
3519   Level: developer
3520 
3521 .seealso: DMSetDS()
3522 @*/
3523 PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
3524 {
3525   PetscFunctionBegin;
3526   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3527   PetscValidPointer(prob, 2);
3528   *prob = dm->prob;
3529   PetscFunctionReturn(0);
3530 }
3531 
3532 #undef __FUNCT__
3533 #define __FUNCT__ "DMSetDS"
3534 /*@
3535   DMSetDS - Set the PetscDS
3536 
3537   Input Parameters:
3538 + dm - The DM
3539 - prob - The PetscDS
3540 
3541   Level: developer
3542 
3543 .seealso: DMGetDS()
3544 @*/
3545 PetscErrorCode DMSetDS(DM dm, PetscDS prob)
3546 {
3547   PetscErrorCode ierr;
3548 
3549   PetscFunctionBegin;
3550   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3551   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2);
3552   ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr);
3553   dm->prob = prob;
3554   ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr);
3555   PetscFunctionReturn(0);
3556 }
3557 
3558 #undef __FUNCT__
3559 #define __FUNCT__ "DMGetNumFields"
3560 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
3561 {
3562   PetscErrorCode ierr;
3563 
3564   PetscFunctionBegin;
3565   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3566   ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr);
3567   PetscFunctionReturn(0);
3568 }
3569 
3570 #undef __FUNCT__
3571 #define __FUNCT__ "DMSetNumFields"
3572 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
3573 {
3574   PetscInt       Nf, f;
3575   PetscErrorCode ierr;
3576 
3577   PetscFunctionBegin;
3578   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3579   ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr);
3580   for (f = Nf; f < numFields; ++f) {
3581     PetscContainer obj;
3582 
3583     ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr);
3584     ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr);
3585     ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr);
3586   }
3587   PetscFunctionReturn(0);
3588 }
3589 
3590 #undef __FUNCT__
3591 #define __FUNCT__ "DMGetField"
3592 /*@
3593   DMGetField - Return the discretization object for a given DM field
3594 
3595   Not collective
3596 
3597   Input Parameters:
3598 + dm - The DM
3599 - f  - The field number
3600 
3601   Output Parameter:
3602 . field - The discretization object
3603 
3604   Level: developer
3605 
3606 .seealso: DMSetField()
3607 @*/
3608 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field)
3609 {
3610   PetscErrorCode ierr;
3611 
3612   PetscFunctionBegin;
3613   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3614   ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr);
3615   PetscFunctionReturn(0);
3616 }
3617 
3618 #undef __FUNCT__
3619 #define __FUNCT__ "DMSetField"
3620 /*@
3621   DMSetField - Set the discretization object for a given DM field
3622 
3623   Logically collective on DM
3624 
3625   Input Parameters:
3626 + dm - The DM
3627 . f  - The field number
3628 - field - The discretization object
3629 
3630   Level: developer
3631 
3632 .seealso: DMGetField()
3633 @*/
3634 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field)
3635 {
3636   PetscErrorCode ierr;
3637 
3638   PetscFunctionBegin;
3639   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3640   ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr);
3641   PetscFunctionReturn(0);
3642 }
3643 
3644 #undef __FUNCT__
3645 #define __FUNCT__ "DMRestrictHook_Coordinates"
3646 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx)
3647 {
3648   DM dm_coord,dmc_coord;
3649   PetscErrorCode ierr;
3650   Vec coords,ccoords;
3651   Mat inject;
3652   PetscFunctionBegin;
3653   ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr);
3654   ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr);
3655   ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
3656   ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr);
3657   if (coords && !ccoords) {
3658     ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr);
3659     ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr);
3660     ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr);
3661     ierr = MatDestroy(&inject);CHKERRQ(ierr);
3662     ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr);
3663     ierr = VecDestroy(&ccoords);CHKERRQ(ierr);
3664   }
3665   PetscFunctionReturn(0);
3666 }
3667 
3668 #undef __FUNCT__
3669 #define __FUNCT__ "DMSubDomainHook_Coordinates"
3670 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx)
3671 {
3672   DM dm_coord,subdm_coord;
3673   PetscErrorCode ierr;
3674   Vec coords,ccoords,clcoords;
3675   VecScatter *scat_i,*scat_g;
3676   PetscFunctionBegin;
3677   ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr);
3678   ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr);
3679   ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
3680   ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr);
3681   if (coords && !ccoords) {
3682     ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr);
3683     ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr);
3684     ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr);
3685     ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3686     ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3687     ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3688     ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3689     ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr);
3690     ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr);
3691     ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr);
3692     ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr);
3693     ierr = VecDestroy(&ccoords);CHKERRQ(ierr);
3694     ierr = VecDestroy(&clcoords);CHKERRQ(ierr);
3695     ierr = PetscFree(scat_i);CHKERRQ(ierr);
3696     ierr = PetscFree(scat_g);CHKERRQ(ierr);
3697   }
3698   PetscFunctionReturn(0);
3699 }
3700 
3701 #undef __FUNCT__
3702 #define __FUNCT__ "DMGetDimension"
3703 /*@
3704   DMGetDimension - Return the topological dimension of the DM
3705 
3706   Not collective
3707 
3708   Input Parameter:
3709 . dm - The DM
3710 
3711   Output Parameter:
3712 . dim - The topological dimension
3713 
3714   Level: beginner
3715 
3716 .seealso: DMSetDimension(), DMCreate()
3717 @*/
3718 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
3719 {
3720   PetscFunctionBegin;
3721   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3722   PetscValidPointer(dim, 2);
3723   *dim = dm->dim;
3724   PetscFunctionReturn(0);
3725 }
3726 
3727 #undef __FUNCT__
3728 #define __FUNCT__ "DMSetDimension"
3729 /*@
3730   DMSetDimension - Set the topological dimension of the DM
3731 
3732   Collective on dm
3733 
3734   Input Parameters:
3735 + dm - The DM
3736 - dim - The topological dimension
3737 
3738   Level: beginner
3739 
3740 .seealso: DMGetDimension(), DMCreate()
3741 @*/
3742 PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
3743 {
3744   PetscFunctionBegin;
3745   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3746   PetscValidLogicalCollectiveInt(dm, dim, 2);
3747   dm->dim = dim;
3748   PetscFunctionReturn(0);
3749 }
3750 
3751 #undef __FUNCT__
3752 #define __FUNCT__ "DMGetDimPoints"
3753 /*@
3754   DMGetDimPoints - Get the half-open interval for all points of a given dimension
3755 
3756   Collective on DM
3757 
3758   Input Parameters:
3759 + dm - the DM
3760 - dim - the dimension
3761 
3762   Output Parameters:
3763 + pStart - The first point of the given dimension
3764 . pEnd - The first point following points of the given dimension
3765 
3766   Note:
3767   The points are vertices in the Hasse diagram encoding the topology. This is explained in
3768   http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme,
3769   then the interval is empty.
3770 
3771   Level: intermediate
3772 
3773 .keywords: point, Hasse Diagram, dimension
3774 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum()
3775 @*/
3776 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
3777 {
3778   PetscInt       d;
3779   PetscErrorCode ierr;
3780 
3781   PetscFunctionBegin;
3782   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3783   ierr = DMGetDimension(dm, &d);CHKERRQ(ierr);
3784   if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d);
3785   ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr);
3786   PetscFunctionReturn(0);
3787 }
3788 
3789 #undef __FUNCT__
3790 #define __FUNCT__ "DMSetCoordinates"
3791 /*@
3792   DMSetCoordinates - Sets into the DM a global vector that holds the coordinates
3793 
3794   Collective on DM
3795 
3796   Input Parameters:
3797 + dm - the DM
3798 - c - coordinate vector
3799 
3800   Note:
3801   The coordinates do include those for ghost points, which are in the local vector
3802 
3803   Level: intermediate
3804 
3805 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3806 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM()
3807 @*/
3808 PetscErrorCode DMSetCoordinates(DM dm, Vec c)
3809 {
3810   PetscErrorCode ierr;
3811 
3812   PetscFunctionBegin;
3813   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3814   PetscValidHeaderSpecific(c,VEC_CLASSID,2);
3815   ierr            = PetscObjectReference((PetscObject) c);CHKERRQ(ierr);
3816   ierr            = VecDestroy(&dm->coordinates);CHKERRQ(ierr);
3817   dm->coordinates = c;
3818   ierr            = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr);
3819   ierr            = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr);
3820   ierr            = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr);
3821   PetscFunctionReturn(0);
3822 }
3823 
3824 #undef __FUNCT__
3825 #define __FUNCT__ "DMSetCoordinatesLocal"
3826 /*@
3827   DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates
3828 
3829   Collective on DM
3830 
3831    Input Parameters:
3832 +  dm - the DM
3833 -  c - coordinate vector
3834 
3835   Note:
3836   The coordinates of ghost points can be set using DMSetCoordinates()
3837   followed by DMGetCoordinatesLocal(). This is intended to enable the
3838   setting of ghost coordinates outside of the domain.
3839 
3840   Level: intermediate
3841 
3842 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3843 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM()
3844 @*/
3845 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c)
3846 {
3847   PetscErrorCode ierr;
3848 
3849   PetscFunctionBegin;
3850   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3851   PetscValidHeaderSpecific(c,VEC_CLASSID,2);
3852   ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr);
3853   ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr);
3854 
3855   dm->coordinatesLocal = c;
3856 
3857   ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr);
3858   PetscFunctionReturn(0);
3859 }
3860 
3861 #undef __FUNCT__
3862 #define __FUNCT__ "DMGetCoordinates"
3863 /*@
3864   DMGetCoordinates - Gets a global vector with the coordinates associated with the DM.
3865 
3866   Not Collective
3867 
3868   Input Parameter:
3869 . dm - the DM
3870 
3871   Output Parameter:
3872 . c - global coordinate vector
3873 
3874   Note:
3875   This is a borrowed reference, so the user should NOT destroy this vector
3876 
3877   Each process has only the local coordinates (does NOT have the ghost coordinates).
3878 
3879   For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
3880   and (x_0,y_0,z_0,x_1,y_1,z_1...)
3881 
3882   Level: intermediate
3883 
3884 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3885 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
3886 @*/
3887 PetscErrorCode DMGetCoordinates(DM dm, Vec *c)
3888 {
3889   PetscErrorCode ierr;
3890 
3891   PetscFunctionBegin;
3892   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3893   PetscValidPointer(c,2);
3894   if (!dm->coordinates && dm->coordinatesLocal) {
3895     DM cdm = NULL;
3896 
3897     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
3898     ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr);
3899     ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr);
3900     ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr);
3901     ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr);
3902   }
3903   *c = dm->coordinates;
3904   PetscFunctionReturn(0);
3905 }
3906 
3907 #undef __FUNCT__
3908 #define __FUNCT__ "DMGetCoordinatesLocal"
3909 /*@
3910   DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM.
3911 
3912   Collective on DM
3913 
3914   Input Parameter:
3915 . dm - the DM
3916 
3917   Output Parameter:
3918 . c - coordinate vector
3919 
3920   Note:
3921   This is a borrowed reference, so the user should NOT destroy this vector
3922 
3923   Each process has the local and ghost coordinates
3924 
3925   For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
3926   and (x_0,y_0,z_0,x_1,y_1,z_1...)
3927 
3928   Level: intermediate
3929 
3930 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3931 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM()
3932 @*/
3933 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c)
3934 {
3935   PetscErrorCode ierr;
3936 
3937   PetscFunctionBegin;
3938   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3939   PetscValidPointer(c,2);
3940   if (!dm->coordinatesLocal && dm->coordinates) {
3941     DM cdm = NULL;
3942 
3943     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
3944     ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr);
3945     ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr);
3946     ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr);
3947     ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr);
3948   }
3949   *c = dm->coordinatesLocal;
3950   PetscFunctionReturn(0);
3951 }
3952 
3953 #undef __FUNCT__
3954 #define __FUNCT__ "DMGetCoordinateDM"
3955 /*@
3956   DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates
3957 
3958   Collective on DM
3959 
3960   Input Parameter:
3961 . dm - the DM
3962 
3963   Output Parameter:
3964 . cdm - coordinate DM
3965 
3966   Level: intermediate
3967 
3968 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3969 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
3970 @*/
3971 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm)
3972 {
3973   PetscErrorCode ierr;
3974 
3975   PetscFunctionBegin;
3976   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3977   PetscValidPointer(cdm,2);
3978   if (!dm->coordinateDM) {
3979     if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM");
3980     ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr);
3981   }
3982   *cdm = dm->coordinateDM;
3983   PetscFunctionReturn(0);
3984 }
3985 
3986 #undef __FUNCT__
3987 #define __FUNCT__ "DMSetCoordinateDM"
3988 /*@
3989   DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates
3990 
3991   Logically Collective on DM
3992 
3993   Input Parameters:
3994 + dm - the DM
3995 - cdm - coordinate DM
3996 
3997   Level: intermediate
3998 
3999 .keywords: distributed array, get, corners, nodes, local indices, coordinates
4000 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4001 @*/
4002 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm)
4003 {
4004   PetscErrorCode ierr;
4005 
4006   PetscFunctionBegin;
4007   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4008   PetscValidHeaderSpecific(cdm,DM_CLASSID,2);
4009   ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr);
4010   dm->coordinateDM = cdm;
4011   ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr);
4012   PetscFunctionReturn(0);
4013 }
4014 
4015 #undef __FUNCT__
4016 #define __FUNCT__ "DMGetCoordinateDim"
4017 /*@
4018   DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values.
4019 
4020   Not Collective
4021 
4022   Input Parameter:
4023 . dm - The DM object
4024 
4025   Output Parameter:
4026 . dim - The embedding dimension
4027 
4028   Level: intermediate
4029 
4030 .keywords: mesh, coordinates
4031 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
4032 @*/
4033 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim)
4034 {
4035   PetscFunctionBegin;
4036   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4037   PetscValidPointer(dim, 2);
4038   if (dm->dimEmbed == PETSC_DEFAULT) {
4039     dm->dimEmbed = dm->dim;
4040   }
4041   *dim = dm->dimEmbed;
4042   PetscFunctionReturn(0);
4043 }
4044 
4045 #undef __FUNCT__
4046 #define __FUNCT__ "DMSetCoordinateDim"
4047 /*@
4048   DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values.
4049 
4050   Not Collective
4051 
4052   Input Parameters:
4053 + dm  - The DM object
4054 - dim - The embedding dimension
4055 
4056   Level: intermediate
4057 
4058 .keywords: mesh, coordinates
4059 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
4060 @*/
4061 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim)
4062 {
4063   PetscFunctionBegin;
4064   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4065   dm->dimEmbed = dim;
4066   PetscFunctionReturn(0);
4067 }
4068 
4069 #undef __FUNCT__
4070 #define __FUNCT__ "DMGetCoordinateSection"
4071 /*@
4072   DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh.
4073 
4074   Not Collective
4075 
4076   Input Parameter:
4077 . dm - The DM object
4078 
4079   Output Parameter:
4080 . section - The PetscSection object
4081 
4082   Level: intermediate
4083 
4084 .keywords: mesh, coordinates
4085 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
4086 @*/
4087 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section)
4088 {
4089   DM             cdm;
4090   PetscErrorCode ierr;
4091 
4092   PetscFunctionBegin;
4093   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4094   PetscValidPointer(section, 2);
4095   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
4096   ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr);
4097   PetscFunctionReturn(0);
4098 }
4099 
4100 #undef __FUNCT__
4101 #define __FUNCT__ "DMSetCoordinateSection"
4102 /*@
4103   DMSetCoordinateSection - Set the layout of coordinate values over the mesh.
4104 
4105   Not Collective
4106 
4107   Input Parameters:
4108 + dm      - The DM object
4109 . dim     - The embedding dimension, or PETSC_DETERMINE
4110 - section - The PetscSection object
4111 
4112   Level: intermediate
4113 
4114 .keywords: mesh, coordinates
4115 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
4116 @*/
4117 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section)
4118 {
4119   DM             cdm;
4120   PetscErrorCode ierr;
4121 
4122   PetscFunctionBegin;
4123   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4124   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3);
4125   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
4126   ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr);
4127   if (dim == PETSC_DETERMINE) {
4128     PetscInt d = dim;
4129     PetscInt pStart, pEnd, vStart, vEnd, v, dd;
4130 
4131     ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
4132     ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
4133     pStart = PetscMax(vStart, pStart);
4134     pEnd   = PetscMin(vEnd, pEnd);
4135     for (v = pStart; v < pEnd; ++v) {
4136       ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr);
4137       if (dd) {d = dd; break;}
4138     }
4139     ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);
4140   }
4141   PetscFunctionReturn(0);
4142 }
4143 
4144 #undef __FUNCT__
4145 #define __FUNCT__ "DMGetPeriodicity"
4146 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L)
4147 {
4148   PetscFunctionBegin;
4149   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4150   if (L)       *L       = dm->L;
4151   if (maxCell) *maxCell = dm->maxCell;
4152   PetscFunctionReturn(0);
4153 }
4154 
4155 #undef __FUNCT__
4156 #define __FUNCT__ "DMSetPeriodicity"
4157 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[])
4158 {
4159   Vec            coordinates;
4160   PetscInt       dim, d;
4161   PetscErrorCode ierr;
4162 
4163   PetscFunctionBegin;
4164   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4165   ierr = PetscFree(dm->L);CHKERRQ(ierr);
4166   ierr = PetscFree(dm->maxCell);CHKERRQ(ierr);
4167   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
4168   ierr = VecGetBlockSize(coordinates, &dim);CHKERRQ(ierr);
4169   ierr = PetscMalloc1(dim,&dm->L);CHKERRQ(ierr);
4170   ierr = PetscMalloc1(dim,&dm->maxCell);CHKERRQ(ierr);
4171   for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d];}
4172   PetscFunctionReturn(0);
4173 }
4174 
4175 #undef __FUNCT__
4176 #define __FUNCT__ "DMLocatePoints"
4177 /*@
4178   DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells
4179 
4180   Not collective
4181 
4182   Input Parameters:
4183 + dm - The DM
4184 - v - The Vec of points
4185 
4186   Output Parameter:
4187 . cells - The local cell numbers for cells which contain the points
4188 
4189   Level: developer
4190 
4191 .keywords: point location, mesh
4192 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4193 @*/
4194 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells)
4195 {
4196   PetscErrorCode ierr;
4197 
4198   PetscFunctionBegin;
4199   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4200   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4201   PetscValidPointer(cells,3);
4202   if (dm->ops->locatepoints) {
4203     ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr);
4204   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM");
4205   PetscFunctionReturn(0);
4206 }
4207 
4208 #undef __FUNCT__
4209 #define __FUNCT__ "DMGetOutputDM"
4210 /*@
4211   DMGetOutputDM - Retrieve the DM associated with the layout for output
4212 
4213   Input Parameter:
4214 . dm - The original DM
4215 
4216   Output Parameter:
4217 . odm - The DM which provides the layout for output
4218 
4219   Level: intermediate
4220 
4221 .seealso: VecView(), DMGetDefaultGlobalSection()
4222 @*/
4223 PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
4224 {
4225   PetscSection   section;
4226   PetscBool      hasConstraints;
4227   PetscErrorCode ierr;
4228 
4229   PetscFunctionBegin;
4230   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4231   PetscValidPointer(odm,2);
4232   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
4233   ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr);
4234   if (!hasConstraints) {
4235     *odm = dm;
4236     PetscFunctionReturn(0);
4237   }
4238   if (!dm->dmBC) {
4239     PetscSection newSection, gsection;
4240     PetscSF      sf;
4241 
4242     ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr);
4243     ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr);
4244     ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr);
4245     ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr);
4246     ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr);
4247     ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, &gsection);CHKERRQ(ierr);
4248     ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr);
4249     ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr);
4250   }
4251   *odm = dm->dmBC;
4252   PetscFunctionReturn(0);
4253 }
4254 
4255 #undef __FUNCT__
4256 #define __FUNCT__ "DMGetOutputSequenceNumber"
4257 /*@
4258   DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
4259 
4260   Input Parameter:
4261 . dm - The original DM
4262 
4263   Output Parameters:
4264 + num - The output sequence number
4265 - val - The output sequence value
4266 
4267   Level: intermediate
4268 
4269   Note: This is intended for output that should appear in sequence, for instance
4270   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
4271 
4272 .seealso: VecView()
4273 @*/
4274 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
4275 {
4276   PetscFunctionBegin;
4277   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4278   if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;}
4279   if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;}
4280   PetscFunctionReturn(0);
4281 }
4282 
4283 #undef __FUNCT__
4284 #define __FUNCT__ "DMSetOutputSequenceNumber"
4285 /*@
4286   DMSetOutputSequenceNumber - Set the sequence number/value for output
4287 
4288   Input Parameters:
4289 + dm - The original DM
4290 . num - The output sequence number
4291 - val - The output sequence value
4292 
4293   Level: intermediate
4294 
4295   Note: This is intended for output that should appear in sequence, for instance
4296   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
4297 
4298 .seealso: VecView()
4299 @*/
4300 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
4301 {
4302   PetscFunctionBegin;
4303   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4304   dm->outputSequenceNum = num;
4305   dm->outputSequenceVal = val;
4306   PetscFunctionReturn(0);
4307 }
4308 
4309 #undef __FUNCT__
4310 #define __FUNCT__ "DMOutputSequenceLoad"
4311 /*@C
4312   DMOutputSequenceLoad - Retrieve the sequence value from a Viewer
4313 
4314   Input Parameters:
4315 + dm   - The original DM
4316 . name - The sequence name
4317 - num  - The output sequence number
4318 
4319   Output Parameter:
4320 . val  - The output sequence value
4321 
4322   Level: intermediate
4323 
4324   Note: This is intended for output that should appear in sequence, for instance
4325   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
4326 
4327 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView()
4328 @*/
4329 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
4330 {
4331   PetscBool      ishdf5;
4332   PetscErrorCode ierr;
4333 
4334   PetscFunctionBegin;
4335   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4336   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4337   PetscValidPointer(val,4);
4338   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
4339   if (ishdf5) {
4340 #if defined(PETSC_HAVE_HDF5)
4341     PetscScalar value;
4342 
4343     ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr);
4344     *val = PetscRealPart(value);
4345 #endif
4346   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
4347   PetscFunctionReturn(0);
4348 }
4349