xref: /petsc/src/dm/interface/dm.c (revision 12fa691eb2a5e4e035852e19d963316c93c71f75)
1 #include <petsc/private/dmimpl.h>           /*I      "petscdm.h"          I*/
2 #include <petsc/private/dmlabelimpl.h>      /*I      "petscdmlabel.h"     I*/
3 #include <petscsf.h>
4 #include <petscds.h>
5 
6 PetscClassId  DM_CLASSID;
7 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_CreateInterpolation;
8 
9 const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DM_BOUNDARY_",0};
10 
11 #undef __FUNCT__
12 #define __FUNCT__ "DMCreate"
13 /*@
14   DMCreate - Creates an empty DM object. The type can then be set with DMSetType().
15 
16    If you never  call DMSetType()  it will generate an
17    error when you try to use the vector.
18 
19   Collective on MPI_Comm
20 
21   Input Parameter:
22 . comm - The communicator for the DM object
23 
24   Output Parameter:
25 . dm - The DM object
26 
27   Level: beginner
28 
29 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK
30 @*/
31 PetscErrorCode  DMCreate(MPI_Comm comm,DM *dm)
32 {
33   DM             v;
34   PetscErrorCode ierr;
35 
36   PetscFunctionBegin;
37   PetscValidPointer(dm,2);
38   *dm = NULL;
39   ierr = PetscSysInitializePackage();CHKERRQ(ierr);
40   ierr = VecInitializePackage();CHKERRQ(ierr);
41   ierr = MatInitializePackage();CHKERRQ(ierr);
42   ierr = DMInitializePackage();CHKERRQ(ierr);
43 
44   ierr = PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr);
45 
46   v->ltogmap                  = NULL;
47   v->bs                       = 1;
48   v->coloringtype             = IS_COLORING_GLOBAL;
49   ierr                        = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr);
50   ierr                        = PetscSFCreate(comm, &v->defaultSF);CHKERRQ(ierr);
51   v->labels                   = NULL;
52   v->depthLabel               = NULL;
53   v->defaultSection           = NULL;
54   v->defaultGlobalSection     = NULL;
55   v->defaultConstraintSection = NULL;
56   v->defaultConstraintMat     = NULL;
57   v->L                        = NULL;
58   v->maxCell                  = NULL;
59   v->bdtype                   = NULL;
60   v->dimEmbed                 = PETSC_DEFAULT;
61   {
62     PetscInt i;
63     for (i = 0; i < 10; ++i) {
64       v->nullspaceConstructors[i] = NULL;
65     }
66   }
67   ierr = PetscDSCreate(comm, &v->prob);CHKERRQ(ierr);
68   v->dmBC = NULL;
69   v->coarseMesh = NULL;
70   v->outputSequenceNum = -1;
71   v->outputSequenceVal = 0.0;
72   ierr = DMSetVecType(v,VECSTANDARD);CHKERRQ(ierr);
73   ierr = DMSetMatType(v,MATAIJ);CHKERRQ(ierr);
74   ierr = PetscNew(&(v->labels));CHKERRQ(ierr);
75   v->labels->refct = 1;
76   ierr = PetscNew(&(v->boundary));CHKERRQ(ierr);
77   v->boundary->refct = 1;
78   *dm = v;
79   PetscFunctionReturn(0);
80 }
81 
82 #undef __FUNCT__
83 #define __FUNCT__ "DMClone"
84 /*@
85   DMClone - Creates a DM object with the same topology as the original.
86 
87   Collective on MPI_Comm
88 
89   Input Parameter:
90 . dm - The original DM object
91 
92   Output Parameter:
93 . newdm  - The new DM object
94 
95   Level: beginner
96 
97 .keywords: DM, topology, create
98 @*/
99 PetscErrorCode DMClone(DM dm, DM *newdm)
100 {
101   PetscSF        sf;
102   Vec            coords;
103   void          *ctx;
104   PetscInt       dim;
105   PetscErrorCode ierr;
106 
107   PetscFunctionBegin;
108   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
109   PetscValidPointer(newdm,2);
110   ierr = DMCreate(PetscObjectComm((PetscObject) dm), newdm);CHKERRQ(ierr);
111   ierr = PetscFree((*newdm)->labels);CHKERRQ(ierr);
112   dm->labels->refct++;
113   (*newdm)->labels = dm->labels;
114   (*newdm)->depthLabel = dm->depthLabel;
115   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
116   ierr = DMSetDimension(*newdm, dim);CHKERRQ(ierr);
117   if (dm->ops->clone) {
118     ierr = (*dm->ops->clone)(dm, newdm);CHKERRQ(ierr);
119   }
120   (*newdm)->setupcalled = dm->setupcalled;
121   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
122   ierr = DMSetPointSF(*newdm, sf);CHKERRQ(ierr);
123   ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr);
124   ierr = DMSetApplicationContext(*newdm, ctx);CHKERRQ(ierr);
125   if (dm->coordinateDM) {
126     DM           ncdm;
127     PetscSection cs;
128     PetscInt     pEnd = -1;
129 
130     ierr = DMGetDefaultSection(dm->coordinateDM, &cs);CHKERRQ(ierr);
131     if (cs) {ierr = PetscSectionGetChart(cs, NULL, &pEnd);CHKERRQ(ierr);}
132     if (pEnd >= 0) {
133       ierr = DMClone(dm->coordinateDM, &ncdm);CHKERRQ(ierr);
134       ierr = DMSetCoordinateDM(*newdm, ncdm);CHKERRQ(ierr);
135       ierr = DMSetDefaultSection(ncdm, cs);CHKERRQ(ierr);
136       ierr = DMDestroy(&ncdm);CHKERRQ(ierr);
137     }
138   }
139   ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr);
140   if (coords) {
141     ierr = DMSetCoordinatesLocal(*newdm, coords);CHKERRQ(ierr);
142   } else {
143     ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr);
144     if (coords) {ierr = DMSetCoordinates(*newdm, coords);CHKERRQ(ierr);}
145   }
146   if (dm->maxCell) {
147     const PetscReal *maxCell, *L;
148     const DMBoundaryType *bd;
149     ierr = DMGetPeriodicity(dm,     &maxCell, &L, &bd);CHKERRQ(ierr);
150     ierr = DMSetPeriodicity(*newdm,  maxCell,  L,  bd);CHKERRQ(ierr);
151   }
152   PetscFunctionReturn(0);
153 }
154 
155 #undef __FUNCT__
156 #define __FUNCT__ "DMSetVecType"
157 /*@C
158        DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
159 
160    Logically Collective on DM
161 
162    Input Parameter:
163 +  da - initial distributed array
164 .  ctype - the vector type, currently either VECSTANDARD or VECCUSP
165 
166    Options Database:
167 .   -dm_vec_type ctype
168 
169    Level: intermediate
170 
171 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMGetVecType()
172 @*/
173 PetscErrorCode  DMSetVecType(DM da,VecType ctype)
174 {
175   PetscErrorCode ierr;
176 
177   PetscFunctionBegin;
178   PetscValidHeaderSpecific(da,DM_CLASSID,1);
179   ierr = PetscFree(da->vectype);CHKERRQ(ierr);
180   ierr = PetscStrallocpy(ctype,(char**)&da->vectype);CHKERRQ(ierr);
181   PetscFunctionReturn(0);
182 }
183 
184 #undef __FUNCT__
185 #define __FUNCT__ "DMGetVecType"
186 /*@C
187        DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
188 
189    Logically Collective on DM
190 
191    Input Parameter:
192 .  da - initial distributed array
193 
194    Output Parameter:
195 .  ctype - the vector type
196 
197    Level: intermediate
198 
199 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType
200 @*/
201 PetscErrorCode  DMGetVecType(DM da,VecType *ctype)
202 {
203   PetscFunctionBegin;
204   PetscValidHeaderSpecific(da,DM_CLASSID,1);
205   *ctype = da->vectype;
206   PetscFunctionReturn(0);
207 }
208 
209 #undef __FUNCT__
210 #define __FUNCT__ "VecGetDM"
211 /*@
212   VecGetDM - Gets the DM defining the data layout of the vector
213 
214   Not collective
215 
216   Input Parameter:
217 . v - The Vec
218 
219   Output Parameter:
220 . dm - The DM
221 
222   Level: intermediate
223 
224 .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
225 @*/
226 PetscErrorCode VecGetDM(Vec v, DM *dm)
227 {
228   PetscErrorCode ierr;
229 
230   PetscFunctionBegin;
231   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
232   PetscValidPointer(dm,2);
233   ierr = PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr);
234   PetscFunctionReturn(0);
235 }
236 
237 #undef __FUNCT__
238 #define __FUNCT__ "VecSetDM"
239 /*@
240   VecSetDM - Sets the DM defining the data layout of the vector.
241 
242   Not collective
243 
244   Input Parameters:
245 + v - The Vec
246 - dm - The DM
247 
248   Note: This is NOT the same as DMCreateGlobalVector() since it does not change the view methods or perform other customization, but merely sets the DM member.
249 
250   Level: intermediate
251 
252 .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
253 @*/
254 PetscErrorCode VecSetDM(Vec v, DM dm)
255 {
256   PetscErrorCode ierr;
257 
258   PetscFunctionBegin;
259   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
260   if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2);
261   ierr = PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr);
262   PetscFunctionReturn(0);
263 }
264 
265 #undef __FUNCT__
266 #define __FUNCT__ "DMSetMatType"
267 /*@C
268        DMSetMatType - Sets the type of matrix created with DMCreateMatrix()
269 
270    Logically Collective on DM
271 
272    Input Parameter:
273 +  dm - the DM context
274 .  ctype - the matrix type
275 
276    Options Database:
277 .   -dm_mat_type ctype
278 
279    Level: intermediate
280 
281 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType()
282 @*/
283 PetscErrorCode  DMSetMatType(DM dm,MatType ctype)
284 {
285   PetscErrorCode ierr;
286 
287   PetscFunctionBegin;
288   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
289   ierr = PetscFree(dm->mattype);CHKERRQ(ierr);
290   ierr = PetscStrallocpy(ctype,(char**)&dm->mattype);CHKERRQ(ierr);
291   PetscFunctionReturn(0);
292 }
293 
294 #undef __FUNCT__
295 #define __FUNCT__ "DMGetMatType"
296 /*@C
297        DMGetMatType - Gets the type of matrix created with DMCreateMatrix()
298 
299    Logically Collective on DM
300 
301    Input Parameter:
302 .  dm - the DM context
303 
304    Output Parameter:
305 .  ctype - the matrix type
306 
307    Options Database:
308 .   -dm_mat_type ctype
309 
310    Level: intermediate
311 
312 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType()
313 @*/
314 PetscErrorCode  DMGetMatType(DM dm,MatType *ctype)
315 {
316   PetscFunctionBegin;
317   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
318   *ctype = dm->mattype;
319   PetscFunctionReturn(0);
320 }
321 
322 #undef __FUNCT__
323 #define __FUNCT__ "MatGetDM"
324 /*@
325   MatGetDM - Gets the DM defining the data layout of the matrix
326 
327   Not collective
328 
329   Input Parameter:
330 . A - The Mat
331 
332   Output Parameter:
333 . dm - The DM
334 
335   Level: intermediate
336 
337 .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType()
338 @*/
339 PetscErrorCode MatGetDM(Mat A, DM *dm)
340 {
341   PetscErrorCode ierr;
342 
343   PetscFunctionBegin;
344   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
345   PetscValidPointer(dm,2);
346   ierr = PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr);
347   PetscFunctionReturn(0);
348 }
349 
350 #undef __FUNCT__
351 #define __FUNCT__ "MatSetDM"
352 /*@
353   MatSetDM - Sets the DM defining the data layout of the matrix
354 
355   Not collective
356 
357   Input Parameters:
358 + A - The Mat
359 - dm - The DM
360 
361   Level: intermediate
362 
363 .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType()
364 @*/
365 PetscErrorCode MatSetDM(Mat A, DM dm)
366 {
367   PetscErrorCode ierr;
368 
369   PetscFunctionBegin;
370   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
371   if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2);
372   ierr = PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr);
373   PetscFunctionReturn(0);
374 }
375 
376 #undef __FUNCT__
377 #define __FUNCT__ "DMSetOptionsPrefix"
378 /*@C
379    DMSetOptionsPrefix - Sets the prefix used for searching for all
380    DM options in the database.
381 
382    Logically Collective on DM
383 
384    Input Parameter:
385 +  da - the DM context
386 -  prefix - the prefix to prepend to all option names
387 
388    Notes:
389    A hyphen (-) must NOT be given at the beginning of the prefix name.
390    The first character of all runtime options is AUTOMATICALLY the hyphen.
391 
392    Level: advanced
393 
394 .keywords: DM, set, options, prefix, database
395 
396 .seealso: DMSetFromOptions()
397 @*/
398 PetscErrorCode  DMSetOptionsPrefix(DM dm,const char prefix[])
399 {
400   PetscErrorCode ierr;
401 
402   PetscFunctionBegin;
403   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
404   ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr);
405   if (dm->sf) {
406     ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->sf,prefix);CHKERRQ(ierr);
407   }
408   if (dm->defaultSF) {
409     ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->defaultSF,prefix);CHKERRQ(ierr);
410   }
411   PetscFunctionReturn(0);
412 }
413 
414 #undef __FUNCT__
415 #define __FUNCT__ "DMAppendOptionsPrefix"
416 /*@C
417    DMAppendOptionsPrefix - Appends to the prefix used for searching for all
418    DM options in the database.
419 
420    Logically Collective on DM
421 
422    Input Parameters:
423 +  dm - the DM context
424 -  prefix - the prefix string to prepend to all DM option requests
425 
426    Notes:
427    A hyphen (-) must NOT be given at the beginning of the prefix name.
428    The first character of all runtime options is AUTOMATICALLY the hyphen.
429 
430    Level: advanced
431 
432 .keywords: DM, append, options, prefix, database
433 
434 .seealso: DMSetOptionsPrefix(), DMGetOptionsPrefix()
435 @*/
436 PetscErrorCode  DMAppendOptionsPrefix(DM dm,const char prefix[])
437 {
438   PetscErrorCode ierr;
439 
440   PetscFunctionBegin;
441   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
442   ierr = PetscObjectAppendOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr);
443   PetscFunctionReturn(0);
444 }
445 
446 #undef __FUNCT__
447 #define __FUNCT__ "DMGetOptionsPrefix"
448 /*@C
449    DMGetOptionsPrefix - Gets the prefix used for searching for all
450    DM options in the database.
451 
452    Not Collective
453 
454    Input Parameters:
455 .  dm - the DM context
456 
457    Output Parameters:
458 .  prefix - pointer to the prefix string used is returned
459 
460    Notes: On the fortran side, the user should pass in a string 'prefix' of
461    sufficient length to hold the prefix.
462 
463    Level: advanced
464 
465 .keywords: DM, set, options, prefix, database
466 
467 .seealso: DMSetOptionsPrefix(), DMAppendOptionsPrefix()
468 @*/
469 PetscErrorCode  DMGetOptionsPrefix(DM dm,const char *prefix[])
470 {
471   PetscErrorCode ierr;
472 
473   PetscFunctionBegin;
474   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
475   ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr);
476   PetscFunctionReturn(0);
477 }
478 
479 #undef __FUNCT__
480 #define __FUNCT__ "DMCountNonCyclicReferences"
481 static PetscErrorCode DMCountNonCyclicReferences(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct)
482 {
483   PetscInt i, refct = ((PetscObject) dm)->refct;
484   DMNamedVecLink nlink;
485   PetscErrorCode ierr;
486 
487   PetscFunctionBegin;
488   /* count all the circular references of DM and its contained Vecs */
489   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
490     if (dm->localin[i])  refct--;
491     if (dm->globalin[i]) refct--;
492   }
493   for (nlink=dm->namedglobal; nlink; nlink=nlink->next) refct--;
494   for (nlink=dm->namedlocal; nlink; nlink=nlink->next) refct--;
495   if (dm->x) {
496     DM obj;
497     ierr = VecGetDM(dm->x, &obj);CHKERRQ(ierr);
498     if (obj == dm) refct--;
499   }
500   if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) {
501     refct--;
502     if (recurseCoarse) {
503       PetscInt coarseCount;
504 
505       ierr = DMCountNonCyclicReferences(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE,&coarseCount);CHKERRQ(ierr);
506       refct += coarseCount;
507     }
508   }
509   if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) {
510     refct--;
511     if (recurseFine) {
512       PetscInt fineCount;
513 
514       ierr = DMCountNonCyclicReferences(dm->fineMesh, PETSC_FALSE, PETSC_TRUE,&fineCount);CHKERRQ(ierr);
515       refct += fineCount;
516     }
517   }
518   *ncrefct = refct;
519   PetscFunctionReturn(0);
520 }
521 
522 PetscErrorCode DMBoundaryDestroy(DMBoundaryLinkList *boundary);
523 
524 #undef __FUNCT__
525 #define __FUNCT__ "DMDestroyLabelLinkList"
526 PetscErrorCode DMDestroyLabelLinkList(DM dm)
527 {
528   PetscErrorCode ierr;
529 
530   PetscFunctionBegin;
531   if (!--(dm->labels->refct)) {
532     DMLabelLink next = dm->labels->next;
533 
534     /* destroy the labels */
535     while (next) {
536       DMLabelLink tmp = next->next;
537 
538       ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr);
539       ierr = PetscFree(next);CHKERRQ(ierr);
540       next = tmp;
541     }
542     ierr = PetscFree(dm->labels);CHKERRQ(ierr);
543   }
544   PetscFunctionReturn(0);
545 }
546 
547 #undef __FUNCT__
548 #define __FUNCT__ "DMDestroy"
549 /*@
550     DMDestroy - Destroys a vector packer or DM.
551 
552     Collective on DM
553 
554     Input Parameter:
555 .   dm - the DM object to destroy
556 
557     Level: developer
558 
559 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
560 
561 @*/
562 PetscErrorCode  DMDestroy(DM *dm)
563 {
564   PetscInt       i, cnt;
565   DMNamedVecLink nlink,nnext;
566   PetscErrorCode ierr;
567 
568   PetscFunctionBegin;
569   if (!*dm) PetscFunctionReturn(0);
570   PetscValidHeaderSpecific((*dm),DM_CLASSID,1);
571 
572   /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */
573   ierr = DMCountNonCyclicReferences(*dm,PETSC_TRUE,PETSC_TRUE,&cnt);CHKERRQ(ierr);
574   --((PetscObject)(*dm))->refct;
575   if (--cnt > 0) {*dm = 0; PetscFunctionReturn(0);}
576   /*
577      Need this test because the dm references the vectors that
578      reference the dm, so destroying the dm calls destroy on the
579      vectors that cause another destroy on the dm
580   */
581   if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0);
582   ((PetscObject) (*dm))->refct = 0;
583   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
584     if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()");
585     ierr = VecDestroy(&(*dm)->localin[i]);CHKERRQ(ierr);
586   }
587   nnext=(*dm)->namedglobal;
588   (*dm)->namedglobal = NULL;
589   for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */
590     nnext = nlink->next;
591     if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
592     ierr = PetscFree(nlink->name);CHKERRQ(ierr);
593     ierr = VecDestroy(&nlink->X);CHKERRQ(ierr);
594     ierr = PetscFree(nlink);CHKERRQ(ierr);
595   }
596   nnext=(*dm)->namedlocal;
597   (*dm)->namedlocal = NULL;
598   for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */
599     nnext = nlink->next;
600     if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
601     ierr = PetscFree(nlink->name);CHKERRQ(ierr);
602     ierr = VecDestroy(&nlink->X);CHKERRQ(ierr);
603     ierr = PetscFree(nlink);CHKERRQ(ierr);
604   }
605 
606   /* Destroy the list of hooks */
607   {
608     DMCoarsenHookLink link,next;
609     for (link=(*dm)->coarsenhook; link; link=next) {
610       next = link->next;
611       ierr = PetscFree(link);CHKERRQ(ierr);
612     }
613     (*dm)->coarsenhook = NULL;
614   }
615   {
616     DMRefineHookLink link,next;
617     for (link=(*dm)->refinehook; link; link=next) {
618       next = link->next;
619       ierr = PetscFree(link);CHKERRQ(ierr);
620     }
621     (*dm)->refinehook = NULL;
622   }
623   {
624     DMSubDomainHookLink link,next;
625     for (link=(*dm)->subdomainhook; link; link=next) {
626       next = link->next;
627       ierr = PetscFree(link);CHKERRQ(ierr);
628     }
629     (*dm)->subdomainhook = NULL;
630   }
631   {
632     DMGlobalToLocalHookLink link,next;
633     for (link=(*dm)->gtolhook; link; link=next) {
634       next = link->next;
635       ierr = PetscFree(link);CHKERRQ(ierr);
636     }
637     (*dm)->gtolhook = NULL;
638   }
639   {
640     DMLocalToGlobalHookLink link,next;
641     for (link=(*dm)->ltoghook; link; link=next) {
642       next = link->next;
643       ierr = PetscFree(link);CHKERRQ(ierr);
644     }
645     (*dm)->ltoghook = NULL;
646   }
647   /* Destroy the work arrays */
648   {
649     DMWorkLink link,next;
650     if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out");
651     for (link=(*dm)->workin; link; link=next) {
652       next = link->next;
653       ierr = PetscFree(link->mem);CHKERRQ(ierr);
654       ierr = PetscFree(link);CHKERRQ(ierr);
655     }
656     (*dm)->workin = NULL;
657   }
658   if (!--((*dm)->labels->refct)) {
659     DMLabelLink next = (*dm)->labels->next;
660 
661     /* destroy the labels */
662     while (next) {
663       DMLabelLink tmp = next->next;
664 
665       ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr);
666       ierr = PetscFree(next);CHKERRQ(ierr);
667       next = tmp;
668     }
669     ierr = PetscFree((*dm)->labels);CHKERRQ(ierr);
670   }
671   ierr = DMBoundaryDestroy(&(*dm)->boundary);CHKERRQ(ierr);
672 
673   ierr = PetscObjectDestroy(&(*dm)->dmksp);CHKERRQ(ierr);
674   ierr = PetscObjectDestroy(&(*dm)->dmsnes);CHKERRQ(ierr);
675   ierr = PetscObjectDestroy(&(*dm)->dmts);CHKERRQ(ierr);
676 
677   if ((*dm)->ctx && (*dm)->ctxdestroy) {
678     ierr = (*(*dm)->ctxdestroy)(&(*dm)->ctx);CHKERRQ(ierr);
679   }
680   ierr = VecDestroy(&(*dm)->x);CHKERRQ(ierr);
681   ierr = MatFDColoringDestroy(&(*dm)->fd);CHKERRQ(ierr);
682   ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr);
683   ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr);
684   ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr);
685   ierr = PetscFree((*dm)->mattype);CHKERRQ(ierr);
686 
687   ierr = PetscSectionDestroy(&(*dm)->defaultSection);CHKERRQ(ierr);
688   ierr = PetscSectionDestroy(&(*dm)->defaultGlobalSection);CHKERRQ(ierr);
689   ierr = PetscLayoutDestroy(&(*dm)->map);CHKERRQ(ierr);
690   ierr = PetscSectionDestroy(&(*dm)->defaultConstraintSection);CHKERRQ(ierr);
691   ierr = MatDestroy(&(*dm)->defaultConstraintMat);CHKERRQ(ierr);
692   ierr = PetscSFDestroy(&(*dm)->sf);CHKERRQ(ierr);
693   ierr = PetscSFDestroy(&(*dm)->defaultSF);CHKERRQ(ierr);
694   ierr = PetscSFDestroy(&(*dm)->sfNatural);CHKERRQ(ierr);
695 
696   if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) {
697     ierr = DMSetFineDM((*dm)->coarseMesh,NULL);CHKERRQ(ierr);
698   }
699   ierr = DMDestroy(&(*dm)->coarseMesh);CHKERRQ(ierr);
700   if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) {
701     ierr = DMSetCoarseDM((*dm)->fineMesh,NULL);CHKERRQ(ierr);
702   }
703   ierr = DMDestroy(&(*dm)->fineMesh);CHKERRQ(ierr);
704   ierr = DMDestroy(&(*dm)->coordinateDM);CHKERRQ(ierr);
705   ierr = VecDestroy(&(*dm)->coordinates);CHKERRQ(ierr);
706   ierr = VecDestroy(&(*dm)->coordinatesLocal);CHKERRQ(ierr);
707   ierr = PetscFree3((*dm)->L,(*dm)->maxCell,(*dm)->bdtype);CHKERRQ(ierr);
708 
709   ierr = PetscDSDestroy(&(*dm)->prob);CHKERRQ(ierr);
710   ierr = DMDestroy(&(*dm)->dmBC);CHKERRQ(ierr);
711   /* if memory was published with SAWs then destroy it */
712   ierr = PetscObjectSAWsViewOff((PetscObject)*dm);CHKERRQ(ierr);
713 
714   ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr);
715   /* We do not destroy (*dm)->data here so that we can reference count backend objects */
716   ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr);
717   PetscFunctionReturn(0);
718 }
719 
720 #undef __FUNCT__
721 #define __FUNCT__ "DMSetUp"
722 /*@
723     DMSetUp - sets up the data structures inside a DM object
724 
725     Collective on DM
726 
727     Input Parameter:
728 .   dm - the DM object to setup
729 
730     Level: developer
731 
732 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
733 
734 @*/
735 PetscErrorCode  DMSetUp(DM dm)
736 {
737   PetscErrorCode ierr;
738 
739   PetscFunctionBegin;
740   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
741   if (dm->setupcalled) PetscFunctionReturn(0);
742   if (dm->ops->setup) {
743     ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr);
744   }
745   dm->setupcalled = PETSC_TRUE;
746   PetscFunctionReturn(0);
747 }
748 
749 #undef __FUNCT__
750 #define __FUNCT__ "DMSetFromOptions"
751 /*@
752     DMSetFromOptions - sets parameters in a DM from the options database
753 
754     Collective on DM
755 
756     Input Parameter:
757 .   dm - the DM object to set options for
758 
759     Options Database:
760 +   -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros
761 .   -dm_vec_type <type>  - type of vector to create inside DM
762 .   -dm_mat_type <type>  - type of matrix to create inside DM
763 -   -dm_coloring_type    - <global or ghosted>
764 
765     Level: developer
766 
767 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
768 
769 @*/
770 PetscErrorCode  DMSetFromOptions(DM dm)
771 {
772   char           typeName[256];
773   PetscBool      flg;
774   PetscErrorCode ierr;
775 
776   PetscFunctionBegin;
777   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
778   if (dm->sf) {
779     ierr = PetscSFSetFromOptions(dm->sf);CHKERRQ(ierr);
780   }
781   if (dm->defaultSF) {
782     ierr = PetscSFSetFromOptions(dm->defaultSF);CHKERRQ(ierr);
783   }
784   ierr = PetscObjectOptionsBegin((PetscObject)dm);CHKERRQ(ierr);
785   ierr = PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);CHKERRQ(ierr);
786   ierr = PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);CHKERRQ(ierr);
787   if (flg) {
788     ierr = DMSetVecType(dm,typeName);CHKERRQ(ierr);
789   }
790   ierr = PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);CHKERRQ(ierr);
791   if (flg) {
792     ierr = DMSetMatType(dm,typeName);CHKERRQ(ierr);
793   }
794   ierr = PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","ISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);CHKERRQ(ierr);
795   if (dm->ops->setfromoptions) {
796     ierr = (*dm->ops->setfromoptions)(PetscOptionsObject,dm);CHKERRQ(ierr);
797   }
798   /* process any options handlers added with PetscObjectAddOptionsHandler() */
799   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) dm);CHKERRQ(ierr);
800   ierr = PetscOptionsEnd();CHKERRQ(ierr);
801   PetscFunctionReturn(0);
802 }
803 
804 #undef __FUNCT__
805 #define __FUNCT__ "DMView"
806 /*@C
807     DMView - Views a DM
808 
809     Collective on DM
810 
811     Input Parameter:
812 +   dm - the DM object to view
813 -   v - the viewer
814 
815     Level: beginner
816 
817 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
818 
819 @*/
820 PetscErrorCode  DMView(DM dm,PetscViewer v)
821 {
822   PetscErrorCode ierr;
823   PetscBool      isbinary;
824 
825   PetscFunctionBegin;
826   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
827   if (!v) {
828     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);CHKERRQ(ierr);
829   }
830   ierr = PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);CHKERRQ(ierr);
831   ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
832   if (isbinary) {
833     PetscInt classid = DM_FILE_CLASSID;
834     char     type[256];
835 
836     ierr = PetscViewerBinaryWrite(v,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
837     ierr = PetscStrncpy(type,((PetscObject)dm)->type_name,256);CHKERRQ(ierr);
838     ierr = PetscViewerBinaryWrite(v,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
839   }
840   if (dm->ops->view) {
841     ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr);
842   }
843   PetscFunctionReturn(0);
844 }
845 
846 #undef __FUNCT__
847 #define __FUNCT__ "DMCreateGlobalVector"
848 /*@
849     DMCreateGlobalVector - Creates a global vector from a DM object
850 
851     Collective on DM
852 
853     Input Parameter:
854 .   dm - the DM object
855 
856     Output Parameter:
857 .   vec - the global vector
858 
859     Level: beginner
860 
861 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
862 
863 @*/
864 PetscErrorCode  DMCreateGlobalVector(DM dm,Vec *vec)
865 {
866   PetscErrorCode ierr;
867 
868   PetscFunctionBegin;
869   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
870   ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr);
871   PetscFunctionReturn(0);
872 }
873 
874 #undef __FUNCT__
875 #define __FUNCT__ "DMCreateLocalVector"
876 /*@
877     DMCreateLocalVector - Creates a local vector from a DM object
878 
879     Not Collective
880 
881     Input Parameter:
882 .   dm - the DM object
883 
884     Output Parameter:
885 .   vec - the local vector
886 
887     Level: beginner
888 
889 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
890 
891 @*/
892 PetscErrorCode  DMCreateLocalVector(DM dm,Vec *vec)
893 {
894   PetscErrorCode ierr;
895 
896   PetscFunctionBegin;
897   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
898   ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr);
899   PetscFunctionReturn(0);
900 }
901 
902 #undef __FUNCT__
903 #define __FUNCT__ "DMGetLocalToGlobalMapping"
904 /*@
905    DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM.
906 
907    Collective on DM
908 
909    Input Parameter:
910 .  dm - the DM that provides the mapping
911 
912    Output Parameter:
913 .  ltog - the mapping
914 
915    Level: intermediate
916 
917    Notes:
918    This mapping can then be used by VecSetLocalToGlobalMapping() or
919    MatSetLocalToGlobalMapping().
920 
921 .seealso: DMCreateLocalVector()
922 @*/
923 PetscErrorCode  DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog)
924 {
925   PetscErrorCode ierr;
926 
927   PetscFunctionBegin;
928   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
929   PetscValidPointer(ltog,2);
930   if (!dm->ltogmap) {
931     PetscSection section, sectionGlobal;
932 
933     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
934     if (section) {
935       PetscInt *ltog;
936       PetscInt pStart, pEnd, size, p, l;
937 
938       ierr = DMGetDefaultGlobalSection(dm, &sectionGlobal);CHKERRQ(ierr);
939       ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
940       ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
941       ierr = PetscMalloc1(size, &ltog);CHKERRQ(ierr); /* We want the local+overlap size */
942       for (p = pStart, l = 0; p < pEnd; ++p) {
943         PetscInt dof, off, c;
944 
945         /* Should probably use constrained dofs */
946         ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
947         ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr);
948         for (c = 0; c < dof; ++c, ++l) {
949           ltog[l] = off+c;
950         }
951       }
952       ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, 1,size, ltog, PETSC_OWN_POINTER, &dm->ltogmap);CHKERRQ(ierr);
953       ierr = PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);CHKERRQ(ierr);
954     } else {
955       if (!dm->ops->getlocaltoglobalmapping) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping");
956       ierr = (*dm->ops->getlocaltoglobalmapping)(dm);CHKERRQ(ierr);
957     }
958   }
959   *ltog = dm->ltogmap;
960   PetscFunctionReturn(0);
961 }
962 
963 #undef __FUNCT__
964 #define __FUNCT__ "DMGetBlockSize"
965 /*@
966    DMGetBlockSize - Gets the inherent block size associated with a DM
967 
968    Not Collective
969 
970    Input Parameter:
971 .  dm - the DM with block structure
972 
973    Output Parameter:
974 .  bs - the block size, 1 implies no exploitable block structure
975 
976    Level: intermediate
977 
978 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping()
979 @*/
980 PetscErrorCode  DMGetBlockSize(DM dm,PetscInt *bs)
981 {
982   PetscFunctionBegin;
983   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
984   PetscValidPointer(bs,2);
985   if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet");
986   *bs = dm->bs;
987   PetscFunctionReturn(0);
988 }
989 
990 #undef __FUNCT__
991 #define __FUNCT__ "DMCreateInterpolation"
992 /*@
993     DMCreateInterpolation - Gets interpolation matrix between two DM objects
994 
995     Collective on DM
996 
997     Input Parameter:
998 +   dm1 - the DM object
999 -   dm2 - the second, finer DM object
1000 
1001     Output Parameter:
1002 +  mat - the interpolation
1003 -  vec - the scaling (optional)
1004 
1005     Level: developer
1006 
1007     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
1008         DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.
1009 
1010         For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors
1011         EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
1012 
1013 
1014 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen()
1015 
1016 @*/
1017 PetscErrorCode  DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec)
1018 {
1019   PetscErrorCode ierr;
1020 
1021   PetscFunctionBegin;
1022   PetscValidHeaderSpecific(dm1,DM_CLASSID,1);
1023   PetscValidHeaderSpecific(dm2,DM_CLASSID,2);
1024   ierr = PetscLogEventBegin(DM_CreateInterpolation,dm1,dm2,0,0);CHKERRQ(ierr);
1025   ierr = (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);CHKERRQ(ierr);
1026   ierr = PetscLogEventEnd(DM_CreateInterpolation,dm1,dm2,0,0);CHKERRQ(ierr);
1027   PetscFunctionReturn(0);
1028 }
1029 
1030 #undef __FUNCT__
1031 #define __FUNCT__ "DMCreateInjection"
1032 /*@
1033     DMCreateInjection - Gets injection matrix between two DM objects
1034 
1035     Collective on DM
1036 
1037     Input Parameter:
1038 +   dm1 - the DM object
1039 -   dm2 - the second, finer DM object
1040 
1041     Output Parameter:
1042 .   mat - the injection
1043 
1044     Level: developer
1045 
1046    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
1047         DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection.
1048 
1049 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation()
1050 
1051 @*/
1052 PetscErrorCode  DMCreateInjection(DM dm1,DM dm2,Mat *mat)
1053 {
1054   PetscErrorCode ierr;
1055 
1056   PetscFunctionBegin;
1057   PetscValidHeaderSpecific(dm1,DM_CLASSID,1);
1058   PetscValidHeaderSpecific(dm2,DM_CLASSID,2);
1059   ierr = (*dm1->ops->getinjection)(dm1,dm2,mat);CHKERRQ(ierr);
1060   PetscFunctionReturn(0);
1061 }
1062 
1063 #undef __FUNCT__
1064 #define __FUNCT__ "DMCreateColoring"
1065 /*@
1066     DMCreateColoring - Gets coloring for a DM
1067 
1068     Collective on DM
1069 
1070     Input Parameter:
1071 +   dm - the DM object
1072 -   ctype - IS_COLORING_GHOSTED or IS_COLORING_GLOBAL
1073 
1074     Output Parameter:
1075 .   coloring - the coloring
1076 
1077     Level: developer
1078 
1079 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType()
1080 
1081 @*/
1082 PetscErrorCode  DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring)
1083 {
1084   PetscErrorCode ierr;
1085 
1086   PetscFunctionBegin;
1087   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1088   if (!dm->ops->getcoloring) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No coloring for this type of DM yet");
1089   ierr = (*dm->ops->getcoloring)(dm,ctype,coloring);CHKERRQ(ierr);
1090   PetscFunctionReturn(0);
1091 }
1092 
1093 #undef __FUNCT__
1094 #define __FUNCT__ "DMCreateMatrix"
1095 /*@
1096     DMCreateMatrix - Gets empty Jacobian for a DM
1097 
1098     Collective on DM
1099 
1100     Input Parameter:
1101 .   dm - the DM object
1102 
1103     Output Parameter:
1104 .   mat - the empty Jacobian
1105 
1106     Level: beginner
1107 
1108     Notes: This properly preallocates the number of nonzeros in the sparse matrix so you
1109        do not need to do it yourself.
1110 
1111        By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
1112        the nonzero pattern call DMDASetMatPreallocateOnly()
1113 
1114        For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used
1115        internally by PETSc.
1116 
1117        For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires
1118        the indices for the global numbering for DMDAs which is complicated.
1119 
1120 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType()
1121 
1122 @*/
1123 PetscErrorCode  DMCreateMatrix(DM dm,Mat *mat)
1124 {
1125   PetscErrorCode ierr;
1126 
1127   PetscFunctionBegin;
1128   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1129   ierr = MatInitializePackage();CHKERRQ(ierr);
1130   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1131   PetscValidPointer(mat,3);
1132   ierr = (*dm->ops->creatematrix)(dm,mat);CHKERRQ(ierr);
1133   PetscFunctionReturn(0);
1134 }
1135 
1136 #undef __FUNCT__
1137 #define __FUNCT__ "DMSetMatrixPreallocateOnly"
1138 /*@
1139   DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly
1140     preallocated but the nonzero structure and zero values will not be set.
1141 
1142   Logically Collective on DM
1143 
1144   Input Parameter:
1145 + dm - the DM
1146 - only - PETSC_TRUE if only want preallocation
1147 
1148   Level: developer
1149 .seealso DMCreateMatrix()
1150 @*/
1151 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
1152 {
1153   PetscFunctionBegin;
1154   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1155   dm->prealloc_only = only;
1156   PetscFunctionReturn(0);
1157 }
1158 
1159 #undef __FUNCT__
1160 #define __FUNCT__ "DMGetWorkArray"
1161 /*@C
1162   DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1163 
1164   Not Collective
1165 
1166   Input Parameters:
1167 + dm - the DM object
1168 . count - The minium size
1169 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT)
1170 
1171   Output Parameter:
1172 . array - the work array
1173 
1174   Level: developer
1175 
1176 .seealso DMDestroy(), DMCreate()
1177 @*/
1178 PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem)
1179 {
1180   PetscErrorCode ierr;
1181   DMWorkLink     link;
1182   size_t         dsize;
1183 
1184   PetscFunctionBegin;
1185   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1186   PetscValidPointer(mem,4);
1187   if (dm->workin) {
1188     link       = dm->workin;
1189     dm->workin = dm->workin->next;
1190   } else {
1191     ierr = PetscNewLog(dm,&link);CHKERRQ(ierr);
1192   }
1193   ierr = PetscDataTypeGetSize(dtype,&dsize);CHKERRQ(ierr);
1194   if (dsize*count > link->bytes) {
1195     ierr        = PetscFree(link->mem);CHKERRQ(ierr);
1196     ierr        = PetscMalloc(dsize*count,&link->mem);CHKERRQ(ierr);
1197     link->bytes = dsize*count;
1198   }
1199   link->next   = dm->workout;
1200   dm->workout  = link;
1201   *(void**)mem = link->mem;
1202   PetscFunctionReturn(0);
1203 }
1204 
1205 #undef __FUNCT__
1206 #define __FUNCT__ "DMRestoreWorkArray"
1207 /*@C
1208   DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1209 
1210   Not Collective
1211 
1212   Input Parameters:
1213 + dm - the DM object
1214 . count - The minium size
1215 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT)
1216 
1217   Output Parameter:
1218 . array - the work array
1219 
1220   Level: developer
1221 
1222 .seealso DMDestroy(), DMCreate()
1223 @*/
1224 PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem)
1225 {
1226   DMWorkLink *p,link;
1227 
1228   PetscFunctionBegin;
1229   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1230   PetscValidPointer(mem,4);
1231   for (p=&dm->workout; (link=*p); p=&link->next) {
1232     if (link->mem == *(void**)mem) {
1233       *p           = link->next;
1234       link->next   = dm->workin;
1235       dm->workin   = link;
1236       *(void**)mem = NULL;
1237       PetscFunctionReturn(0);
1238     }
1239   }
1240   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out");
1241 }
1242 
1243 #undef __FUNCT__
1244 #define __FUNCT__ "DMSetNullSpaceConstructor"
1245 PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace))
1246 {
1247   PetscFunctionBegin;
1248   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1249   if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1250   dm->nullspaceConstructors[field] = nullsp;
1251   PetscFunctionReturn(0);
1252 }
1253 
1254 #undef __FUNCT__
1255 #define __FUNCT__ "DMCreateFieldIS"
1256 /*@C
1257   DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field
1258 
1259   Not collective
1260 
1261   Input Parameter:
1262 . dm - the DM object
1263 
1264   Output Parameters:
1265 + numFields  - The number of fields (or NULL if not requested)
1266 . fieldNames - The name for each field (or NULL if not requested)
1267 - fields     - The global indices for each field (or NULL if not requested)
1268 
1269   Level: intermediate
1270 
1271   Notes:
1272   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1273   PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with
1274   PetscFree().
1275 
1276 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
1277 @*/
1278 PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1279 {
1280   PetscSection   section, sectionGlobal;
1281   PetscErrorCode ierr;
1282 
1283   PetscFunctionBegin;
1284   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1285   if (numFields) {
1286     PetscValidPointer(numFields,2);
1287     *numFields = 0;
1288   }
1289   if (fieldNames) {
1290     PetscValidPointer(fieldNames,3);
1291     *fieldNames = NULL;
1292   }
1293   if (fields) {
1294     PetscValidPointer(fields,4);
1295     *fields = NULL;
1296   }
1297   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
1298   if (section) {
1299     PetscInt *fieldSizes, **fieldIndices;
1300     PetscInt nF, f, pStart, pEnd, p;
1301 
1302     ierr = DMGetDefaultGlobalSection(dm, &sectionGlobal);CHKERRQ(ierr);
1303     ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr);
1304     ierr = PetscMalloc2(nF,&fieldSizes,nF,&fieldIndices);CHKERRQ(ierr);
1305     ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr);
1306     for (f = 0; f < nF; ++f) {
1307       fieldSizes[f] = 0;
1308     }
1309     for (p = pStart; p < pEnd; ++p) {
1310       PetscInt gdof;
1311 
1312       ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr);
1313       if (gdof > 0) {
1314         for (f = 0; f < nF; ++f) {
1315           PetscInt fdof, fcdof;
1316 
1317           ierr           = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr);
1318           ierr           = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr);
1319           fieldSizes[f] += fdof-fcdof;
1320         }
1321       }
1322     }
1323     for (f = 0; f < nF; ++f) {
1324       ierr          = PetscMalloc1(fieldSizes[f], &fieldIndices[f]);CHKERRQ(ierr);
1325       fieldSizes[f] = 0;
1326     }
1327     for (p = pStart; p < pEnd; ++p) {
1328       PetscInt gdof, goff;
1329 
1330       ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr);
1331       if (gdof > 0) {
1332         ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr);
1333         for (f = 0; f < nF; ++f) {
1334           PetscInt fdof, fcdof, fc;
1335 
1336           ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr);
1337           ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr);
1338           for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) {
1339             fieldIndices[f][fieldSizes[f]] = goff++;
1340           }
1341         }
1342       }
1343     }
1344     if (numFields) *numFields = nF;
1345     if (fieldNames) {
1346       ierr = PetscMalloc1(nF, fieldNames);CHKERRQ(ierr);
1347       for (f = 0; f < nF; ++f) {
1348         const char *fieldName;
1349 
1350         ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr);
1351         ierr = PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);CHKERRQ(ierr);
1352       }
1353     }
1354     if (fields) {
1355       ierr = PetscMalloc1(nF, fields);CHKERRQ(ierr);
1356       for (f = 0; f < nF; ++f) {
1357         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);CHKERRQ(ierr);
1358       }
1359     }
1360     ierr = PetscFree2(fieldSizes,fieldIndices);CHKERRQ(ierr);
1361   } else if (dm->ops->createfieldis) {
1362     ierr = (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);CHKERRQ(ierr);
1363   }
1364   PetscFunctionReturn(0);
1365 }
1366 
1367 
1368 #undef __FUNCT__
1369 #define __FUNCT__ "DMCreateFieldDecomposition"
1370 /*@C
1371   DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems
1372                           corresponding to different fields: each IS contains the global indices of the dofs of the
1373                           corresponding field. The optional list of DMs define the DM for each subproblem.
1374                           Generalizes DMCreateFieldIS().
1375 
1376   Not collective
1377 
1378   Input Parameter:
1379 . dm - the DM object
1380 
1381   Output Parameters:
1382 + len       - The number of subproblems in the field decomposition (or NULL if not requested)
1383 . namelist  - The name for each field (or NULL if not requested)
1384 . islist    - The global indices for each field (or NULL if not requested)
1385 - dmlist    - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1386 
1387   Level: intermediate
1388 
1389   Notes:
1390   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1391   PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1392   and all of the arrays should be freed with PetscFree().
1393 
1394 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1395 @*/
1396 PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
1397 {
1398   PetscErrorCode ierr;
1399 
1400   PetscFunctionBegin;
1401   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1402   if (len) {
1403     PetscValidPointer(len,2);
1404     *len = 0;
1405   }
1406   if (namelist) {
1407     PetscValidPointer(namelist,3);
1408     *namelist = 0;
1409   }
1410   if (islist) {
1411     PetscValidPointer(islist,4);
1412     *islist = 0;
1413   }
1414   if (dmlist) {
1415     PetscValidPointer(dmlist,5);
1416     *dmlist = 0;
1417   }
1418   /*
1419    Is it a good idea to apply the following check across all impls?
1420    Perhaps some impls can have a well-defined decomposition before DMSetUp?
1421    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1422    */
1423   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1424   if (!dm->ops->createfielddecomposition) {
1425     PetscSection section;
1426     PetscInt     numFields, f;
1427 
1428     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
1429     if (section) {ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);}
1430     if (section && numFields && dm->ops->createsubdm) {
1431       *len = numFields;
1432       if (namelist) {ierr = PetscMalloc1(numFields,namelist);CHKERRQ(ierr);}
1433       if (islist)   {ierr = PetscMalloc1(numFields,islist);CHKERRQ(ierr);}
1434       if (dmlist)   {ierr = PetscMalloc1(numFields,dmlist);CHKERRQ(ierr);}
1435       for (f = 0; f < numFields; ++f) {
1436         const char *fieldName;
1437 
1438         ierr = DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);CHKERRQ(ierr);
1439         if (namelist) {
1440           ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr);
1441           ierr = PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);CHKERRQ(ierr);
1442         }
1443       }
1444     } else {
1445       ierr = DMCreateFieldIS(dm, len, namelist, islist);CHKERRQ(ierr);
1446       /* By default there are no DMs associated with subproblems. */
1447       if (dmlist) *dmlist = NULL;
1448     }
1449   } else {
1450     ierr = (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);CHKERRQ(ierr);
1451   }
1452   PetscFunctionReturn(0);
1453 }
1454 
1455 #undef __FUNCT__
1456 #define __FUNCT__ "DMCreateSubDM"
1457 /*@
1458   DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in.
1459                   The fields are defined by DMCreateFieldIS().
1460 
1461   Not collective
1462 
1463   Input Parameters:
1464 + dm - the DM object
1465 . numFields - number of fields in this subproblem
1466 - len       - The number of subproblems in the decomposition (or NULL if not requested)
1467 
1468   Output Parameters:
1469 . is - The global indices for the subproblem
1470 - dm - The DM for the subproblem
1471 
1472   Level: intermediate
1473 
1474 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1475 @*/
1476 PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
1477 {
1478   PetscErrorCode ierr;
1479 
1480   PetscFunctionBegin;
1481   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1482   PetscValidPointer(fields,3);
1483   if (is) PetscValidPointer(is,4);
1484   if (subdm) PetscValidPointer(subdm,5);
1485   if (dm->ops->createsubdm) {
1486     ierr = (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);CHKERRQ(ierr);
1487   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined");
1488   PetscFunctionReturn(0);
1489 }
1490 
1491 
1492 #undef __FUNCT__
1493 #define __FUNCT__ "DMCreateDomainDecomposition"
1494 /*@C
1495   DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems
1496                           corresponding to restrictions to pairs nested subdomains: each IS contains the global
1497                           indices of the dofs of the corresponding subdomains.  The inner subdomains conceptually
1498                           define a nonoverlapping covering, while outer subdomains can overlap.
1499                           The optional list of DMs define the DM for each subproblem.
1500 
1501   Not collective
1502 
1503   Input Parameter:
1504 . dm - the DM object
1505 
1506   Output Parameters:
1507 + len         - The number of subproblems in the domain decomposition (or NULL if not requested)
1508 . namelist    - The name for each subdomain (or NULL if not requested)
1509 . innerislist - The global indices for each inner subdomain (or NULL, if not requested)
1510 . outerislist - The global indices for each outer subdomain (or NULL, if not requested)
1511 - dmlist      - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1512 
1513   Level: intermediate
1514 
1515   Notes:
1516   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1517   PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1518   and all of the arrays should be freed with PetscFree().
1519 
1520 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition()
1521 @*/
1522 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
1523 {
1524   PetscErrorCode      ierr;
1525   DMSubDomainHookLink link;
1526   PetscInt            i,l;
1527 
1528   PetscFunctionBegin;
1529   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1530   if (len)           {PetscValidPointer(len,2);            *len         = 0;}
1531   if (namelist)      {PetscValidPointer(namelist,3);       *namelist    = NULL;}
1532   if (innerislist)   {PetscValidPointer(innerislist,4);    *innerislist = NULL;}
1533   if (outerislist)   {PetscValidPointer(outerislist,5);    *outerislist = NULL;}
1534   if (dmlist)        {PetscValidPointer(dmlist,6);         *dmlist      = NULL;}
1535   /*
1536    Is it a good idea to apply the following check across all impls?
1537    Perhaps some impls can have a well-defined decomposition before DMSetUp?
1538    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1539    */
1540   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1541   if (dm->ops->createdomaindecomposition) {
1542     ierr = (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);CHKERRQ(ierr);
1543     /* copy subdomain hooks and context over to the subdomain DMs */
1544     if (dmlist) {
1545       for (i = 0; i < l; i++) {
1546         for (link=dm->subdomainhook; link; link=link->next) {
1547           if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);}
1548         }
1549         (*dmlist)[i]->ctx = dm->ctx;
1550       }
1551     }
1552     if (len) *len = l;
1553   }
1554   PetscFunctionReturn(0);
1555 }
1556 
1557 
1558 #undef __FUNCT__
1559 #define __FUNCT__ "DMCreateDomainDecompositionScatters"
1560 /*@C
1561   DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector
1562 
1563   Not collective
1564 
1565   Input Parameters:
1566 + dm - the DM object
1567 . n  - the number of subdomain scatters
1568 - subdms - the local subdomains
1569 
1570   Output Parameters:
1571 + n     - the number of scatters returned
1572 . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain
1573 . oscat - scatter from global vector to overlapping global vector entries on subdomain
1574 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts)
1575 
1576   Notes: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution
1577   of general nonlinear problems with overlapping subdomain methods.  While merely having index sets that enable subsets
1578   of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of
1579   solution and residual data.
1580 
1581   Level: developer
1582 
1583 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1584 @*/
1585 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat)
1586 {
1587   PetscErrorCode ierr;
1588 
1589   PetscFunctionBegin;
1590   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1591   PetscValidPointer(subdms,3);
1592   if (dm->ops->createddscatters) {
1593     ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr);
1594   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionLocalScatter implementation defined");
1595   PetscFunctionReturn(0);
1596 }
1597 
1598 #undef __FUNCT__
1599 #define __FUNCT__ "DMRefine"
1600 /*@
1601   DMRefine - Refines a DM object
1602 
1603   Collective on DM
1604 
1605   Input Parameter:
1606 + dm   - the DM object
1607 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
1608 
1609   Output Parameter:
1610 . dmf - the refined DM, or NULL
1611 
1612   Note: If no refinement was done, the return value is NULL
1613 
1614   Level: developer
1615 
1616 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1617 @*/
1618 PetscErrorCode  DMRefine(DM dm,MPI_Comm comm,DM *dmf)
1619 {
1620   PetscErrorCode   ierr;
1621   DMRefineHookLink link;
1622 
1623   PetscFunctionBegin;
1624   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1625   ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr);
1626   if (*dmf) {
1627     (*dmf)->ops->creatematrix = dm->ops->creatematrix;
1628 
1629     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr);
1630 
1631     (*dmf)->ctx       = dm->ctx;
1632     (*dmf)->leveldown = dm->leveldown;
1633     (*dmf)->levelup   = dm->levelup + 1;
1634 
1635     ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr);
1636     for (link=dm->refinehook; link; link=link->next) {
1637       if (link->refinehook) {
1638         ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr);
1639       }
1640     }
1641   }
1642   PetscFunctionReturn(0);
1643 }
1644 
1645 #undef __FUNCT__
1646 #define __FUNCT__ "DMRefineHookAdd"
1647 /*@C
1648    DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid
1649 
1650    Logically Collective
1651 
1652    Input Arguments:
1653 +  coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
1654 .  refinehook - function to run when setting up a coarser level
1655 .  interphook - function to run to update data on finer levels (once per SNESSolve())
1656 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1657 
1658    Calling sequence of refinehook:
1659 $    refinehook(DM coarse,DM fine,void *ctx);
1660 
1661 +  coarse - coarse level DM
1662 .  fine - fine level DM to interpolate problem to
1663 -  ctx - optional user-defined function context
1664 
1665    Calling sequence for interphook:
1666 $    interphook(DM coarse,Mat interp,DM fine,void *ctx)
1667 
1668 +  coarse - coarse level DM
1669 .  interp - matrix interpolating a coarse-level solution to the finer grid
1670 .  fine - fine level DM to update
1671 -  ctx - optional user-defined function context
1672 
1673    Level: advanced
1674 
1675    Notes:
1676    This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing
1677 
1678    If this function is called multiple times, the hooks will be run in the order they are added.
1679 
1680    This function is currently not available from Fortran.
1681 
1682 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1683 @*/
1684 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
1685 {
1686   PetscErrorCode   ierr;
1687   DMRefineHookLink link,*p;
1688 
1689   PetscFunctionBegin;
1690   PetscValidHeaderSpecific(coarse,DM_CLASSID,1);
1691   for (p=&coarse->refinehook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
1692   ierr             = PetscMalloc(sizeof(struct _DMRefineHookLink),&link);CHKERRQ(ierr);
1693   link->refinehook = refinehook;
1694   link->interphook = interphook;
1695   link->ctx        = ctx;
1696   link->next       = NULL;
1697   *p               = link;
1698   PetscFunctionReturn(0);
1699 }
1700 
1701 #undef __FUNCT__
1702 #define __FUNCT__ "DMInterpolate"
1703 /*@
1704    DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd()
1705 
1706    Collective if any hooks are
1707 
1708    Input Arguments:
1709 +  coarse - coarser DM to use as a base
1710 .  restrct - interpolation matrix, apply using MatInterpolate()
1711 -  fine - finer DM to update
1712 
1713    Level: developer
1714 
1715 .seealso: DMRefineHookAdd(), MatInterpolate()
1716 @*/
1717 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine)
1718 {
1719   PetscErrorCode   ierr;
1720   DMRefineHookLink link;
1721 
1722   PetscFunctionBegin;
1723   for (link=fine->refinehook; link; link=link->next) {
1724     if (link->interphook) {
1725       ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr);
1726     }
1727   }
1728   PetscFunctionReturn(0);
1729 }
1730 
1731 #undef __FUNCT__
1732 #define __FUNCT__ "DMGetRefineLevel"
1733 /*@
1734     DMGetRefineLevel - Get's the number of refinements that have generated this DM.
1735 
1736     Not Collective
1737 
1738     Input Parameter:
1739 .   dm - the DM object
1740 
1741     Output Parameter:
1742 .   level - number of refinements
1743 
1744     Level: developer
1745 
1746 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1747 
1748 @*/
1749 PetscErrorCode  DMGetRefineLevel(DM dm,PetscInt *level)
1750 {
1751   PetscFunctionBegin;
1752   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1753   *level = dm->levelup;
1754   PetscFunctionReturn(0);
1755 }
1756 
1757 #undef __FUNCT__
1758 #define __FUNCT__ "DMGlobalToLocalHookAdd"
1759 /*@C
1760    DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called
1761 
1762    Logically Collective
1763 
1764    Input Arguments:
1765 +  dm - the DM
1766 .  beginhook - function to run at the beginning of DMGlobalToLocalBegin()
1767 .  endhook - function to run after DMGlobalToLocalEnd() has completed
1768 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1769 
1770    Calling sequence for beginhook:
1771 $    beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
1772 
1773 +  dm - global DM
1774 .  g - global vector
1775 .  mode - mode
1776 .  l - local vector
1777 -  ctx - optional user-defined function context
1778 
1779 
1780    Calling sequence for endhook:
1781 $    endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
1782 
1783 +  global - global DM
1784 -  ctx - optional user-defined function context
1785 
1786    Level: advanced
1787 
1788 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1789 @*/
1790 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
1791 {
1792   PetscErrorCode          ierr;
1793   DMGlobalToLocalHookLink link,*p;
1794 
1795   PetscFunctionBegin;
1796   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1797   for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
1798   ierr            = PetscMalloc(sizeof(struct _DMGlobalToLocalHookLink),&link);CHKERRQ(ierr);
1799   link->beginhook = beginhook;
1800   link->endhook   = endhook;
1801   link->ctx       = ctx;
1802   link->next      = NULL;
1803   *p              = link;
1804   PetscFunctionReturn(0);
1805 }
1806 
1807 #undef __FUNCT__
1808 #define __FUNCT__ "DMGlobalToLocalHook_Constraints"
1809 static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx)
1810 {
1811   Mat cMat;
1812   Vec cVec;
1813   PetscSection section, cSec;
1814   PetscInt pStart, pEnd, p, dof;
1815   PetscErrorCode ierr;
1816 
1817   PetscFunctionBegin;
1818   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1819   ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr);
1820   if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) {
1821     ierr = DMGetDefaultSection(dm,&section);CHKERRQ(ierr);
1822     ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr);
1823     ierr = MatMult(cMat,l,cVec);CHKERRQ(ierr);
1824     ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr);
1825     for (p = pStart; p < pEnd; p++) {
1826       ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr);
1827       if (dof) {
1828         PetscScalar *vals;
1829         ierr = VecGetValuesSection(cVec,cSec,p,&vals);CHKERRQ(ierr);
1830         ierr = VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);CHKERRQ(ierr);
1831       }
1832     }
1833     ierr = VecDestroy(&cVec);CHKERRQ(ierr);
1834   }
1835   PetscFunctionReturn(0);
1836 }
1837 
1838 #undef __FUNCT__
1839 #define __FUNCT__ "DMGlobalToLocalBegin"
1840 /*@
1841     DMGlobalToLocalBegin - Begins updating local vectors from global vector
1842 
1843     Neighbor-wise Collective on DM
1844 
1845     Input Parameters:
1846 +   dm - the DM object
1847 .   g - the global vector
1848 .   mode - INSERT_VALUES or ADD_VALUES
1849 -   l - the local vector
1850 
1851 
1852     Level: beginner
1853 
1854 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
1855 
1856 @*/
1857 PetscErrorCode  DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
1858 {
1859   PetscSF                 sf;
1860   PetscErrorCode          ierr;
1861   DMGlobalToLocalHookLink link;
1862 
1863   PetscFunctionBegin;
1864   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1865   for (link=dm->gtolhook; link; link=link->next) {
1866     if (link->beginhook) {
1867       ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);
1868     }
1869   }
1870   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1871   if (sf) {
1872     const PetscScalar *gArray;
1873     PetscScalar       *lArray;
1874 
1875     if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1876     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1877     ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr);
1878     ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr);
1879     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1880     ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr);
1881   } else {
1882     ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
1883   }
1884   PetscFunctionReturn(0);
1885 }
1886 
1887 #undef __FUNCT__
1888 #define __FUNCT__ "DMGlobalToLocalEnd"
1889 /*@
1890     DMGlobalToLocalEnd - Ends updating local vectors from global vector
1891 
1892     Neighbor-wise Collective on DM
1893 
1894     Input Parameters:
1895 +   dm - the DM object
1896 .   g - the global vector
1897 .   mode - INSERT_VALUES or ADD_VALUES
1898 -   l - the local vector
1899 
1900 
1901     Level: beginner
1902 
1903 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
1904 
1905 @*/
1906 PetscErrorCode  DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
1907 {
1908   PetscSF                 sf;
1909   PetscErrorCode          ierr;
1910   const PetscScalar      *gArray;
1911   PetscScalar            *lArray;
1912   DMGlobalToLocalHookLink link;
1913 
1914   PetscFunctionBegin;
1915   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1916   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1917   if (sf) {
1918     if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1919 
1920     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1921     ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr);
1922     ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr);
1923     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1924     ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr);
1925   } else {
1926     ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
1927   }
1928   ierr = DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);CHKERRQ(ierr);
1929   for (link=dm->gtolhook; link; link=link->next) {
1930     if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);}
1931   }
1932   PetscFunctionReturn(0);
1933 }
1934 
1935 #undef __FUNCT__
1936 #define __FUNCT__ "DMLocalToGlobalHookAdd"
1937 /*@C
1938    DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called
1939 
1940    Logically Collective
1941 
1942    Input Arguments:
1943 +  dm - the DM
1944 .  beginhook - function to run at the beginning of DMLocalToGlobalBegin()
1945 .  endhook - function to run after DMLocalToGlobalEnd() has completed
1946 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1947 
1948    Calling sequence for beginhook:
1949 $    beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
1950 
1951 +  dm - global DM
1952 .  l - local vector
1953 .  mode - mode
1954 .  g - global vector
1955 -  ctx - optional user-defined function context
1956 
1957 
1958    Calling sequence for endhook:
1959 $    endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
1960 
1961 +  global - global DM
1962 .  l - local vector
1963 .  mode - mode
1964 .  g - global vector
1965 -  ctx - optional user-defined function context
1966 
1967    Level: advanced
1968 
1969 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1970 @*/
1971 PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
1972 {
1973   PetscErrorCode          ierr;
1974   DMLocalToGlobalHookLink link,*p;
1975 
1976   PetscFunctionBegin;
1977   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1978   for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
1979   ierr            = PetscMalloc(sizeof(struct _DMLocalToGlobalHookLink),&link);CHKERRQ(ierr);
1980   link->beginhook = beginhook;
1981   link->endhook   = endhook;
1982   link->ctx       = ctx;
1983   link->next      = NULL;
1984   *p              = link;
1985   PetscFunctionReturn(0);
1986 }
1987 
1988 #undef __FUNCT__
1989 #define __FUNCT__ "DMLocalToGlobalHook_Constraints"
1990 static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx)
1991 {
1992   Mat cMat;
1993   Vec cVec;
1994   PetscSection section, cSec;
1995   PetscInt pStart, pEnd, p, dof;
1996   PetscErrorCode ierr;
1997 
1998   PetscFunctionBegin;
1999   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2000   ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr);
2001   if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) {
2002     ierr = DMGetDefaultSection(dm,&section);CHKERRQ(ierr);
2003     ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr);
2004     ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr);
2005     for (p = pStart; p < pEnd; p++) {
2006       ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr);
2007       if (dof) {
2008         PetscInt d;
2009         PetscScalar *vals;
2010         ierr = VecGetValuesSection(l,section,p,&vals);CHKERRQ(ierr);
2011         ierr = VecSetValuesSection(cVec,cSec,p,vals,mode);CHKERRQ(ierr);
2012         /* for this to be the true transpose, we have to zero the values that
2013          * we just extracted */
2014         for (d = 0; d < dof; d++) {
2015           vals[d] = 0.;
2016         }
2017       }
2018     }
2019     ierr = MatMultTransposeAdd(cMat,cVec,l,l);CHKERRQ(ierr);
2020     ierr = VecDestroy(&cVec);CHKERRQ(ierr);
2021   }
2022   PetscFunctionReturn(0);
2023 }
2024 
2025 #undef __FUNCT__
2026 #define __FUNCT__ "DMLocalToGlobalBegin"
2027 /*@
2028     DMLocalToGlobalBegin - updates global vectors from local vectors
2029 
2030     Neighbor-wise Collective on DM
2031 
2032     Input Parameters:
2033 +   dm - the DM object
2034 .   l - the local vector
2035 .   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.
2036 -   g - the global vector
2037 
2038     Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation.
2039            INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one.
2040 
2041     Level: beginner
2042 
2043 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()
2044 
2045 @*/
2046 PetscErrorCode  DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
2047 {
2048   PetscSF                 sf;
2049   PetscSection            s, gs;
2050   DMLocalToGlobalHookLink link;
2051   const PetscScalar      *lArray;
2052   PetscScalar            *gArray;
2053   PetscBool               isInsert;
2054   PetscErrorCode          ierr;
2055 
2056   PetscFunctionBegin;
2057   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2058   for (link=dm->ltoghook; link; link=link->next) {
2059     if (link->beginhook) {
2060       ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr);
2061     }
2062   }
2063   ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr);
2064   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
2065   ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
2066   switch (mode) {
2067   case INSERT_VALUES:
2068   case INSERT_ALL_VALUES:
2069     isInsert = PETSC_TRUE; break;
2070   case ADD_VALUES:
2071   case ADD_ALL_VALUES:
2072     isInsert = PETSC_FALSE; break;
2073   default:
2074     SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2075   }
2076   if (sf && !isInsert) {
2077     ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr);
2078     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
2079     ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr);
2080     ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr);
2081     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
2082   } else if (s && isInsert) {
2083     PetscInt gStart, pStart, pEnd, p;
2084 
2085     ierr = DMGetDefaultGlobalSection(dm, &gs);CHKERRQ(ierr);
2086     ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
2087     ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr);
2088     ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr);
2089     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
2090     for (p = pStart; p < pEnd; ++p) {
2091       PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;
2092 
2093       ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
2094       ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr);
2095       ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
2096       ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr);
2097       ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr);
2098       ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr);
2099       /* Ignore off-process data and points with no global data */
2100       if (!gdof || goff < 0) continue;
2101       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);
2102       /* If no constraints are enforced in the global vector */
2103       if (!gcdof) {
2104         for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d];
2105       /* If constraints are enforced in the global vector */
2106       } else if (cdof == gcdof) {
2107         const PetscInt *cdofs;
2108         PetscInt        cind = 0;
2109 
2110         ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr);
2111         for (d = 0, e = 0; d < dof; ++d) {
2112           if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;}
2113           gArray[goff-gStart+e++] = lArray[off+d];
2114         }
2115       } 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);
2116     }
2117     ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr);
2118     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
2119   } else {
2120     ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr);
2121   }
2122   PetscFunctionReturn(0);
2123 }
2124 
2125 #undef __FUNCT__
2126 #define __FUNCT__ "DMLocalToGlobalEnd"
2127 /*@
2128     DMLocalToGlobalEnd - updates global vectors from local vectors
2129 
2130     Neighbor-wise Collective on DM
2131 
2132     Input Parameters:
2133 +   dm - the DM object
2134 .   l - the local vector
2135 .   mode - INSERT_VALUES or ADD_VALUES
2136 -   g - the global vector
2137 
2138 
2139     Level: beginner
2140 
2141 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()
2142 
2143 @*/
2144 PetscErrorCode  DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
2145 {
2146   PetscSF                 sf;
2147   PetscSection            s;
2148   DMLocalToGlobalHookLink link;
2149   PetscBool               isInsert;
2150   PetscErrorCode          ierr;
2151 
2152   PetscFunctionBegin;
2153   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2154   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
2155   ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
2156   switch (mode) {
2157   case INSERT_VALUES:
2158   case INSERT_ALL_VALUES:
2159     isInsert = PETSC_TRUE; break;
2160   case ADD_VALUES:
2161   case ADD_ALL_VALUES:
2162     isInsert = PETSC_FALSE; break;
2163   default:
2164     SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2165   }
2166   if (sf && !isInsert) {
2167     const PetscScalar *lArray;
2168     PetscScalar       *gArray;
2169 
2170     ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr);
2171     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
2172     ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr);
2173     ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr);
2174     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
2175   } else if (s && isInsert) {
2176   } else {
2177     ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr);
2178   }
2179   for (link=dm->ltoghook; link; link=link->next) {
2180     if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);}
2181   }
2182   PetscFunctionReturn(0);
2183 }
2184 
2185 #undef __FUNCT__
2186 #define __FUNCT__ "DMLocalToLocalBegin"
2187 /*@
2188    DMLocalToLocalBegin - Maps from a local vector (including ghost points
2189    that contain irrelevant values) to another local vector where the ghost
2190    points in the second are set correctly. Must be followed by DMLocalToLocalEnd().
2191 
2192    Neighbor-wise Collective on DM and Vec
2193 
2194    Input Parameters:
2195 +  dm - the DM object
2196 .  g - the original local vector
2197 -  mode - one of INSERT_VALUES or ADD_VALUES
2198 
2199    Output Parameter:
2200 .  l  - the local vector with correct ghost values
2201 
2202    Level: intermediate
2203 
2204    Notes:
2205    The local vectors used here need not be the same as those
2206    obtained from DMCreateLocalVector(), BUT they
2207    must have the same parallel data layout; they could, for example, be
2208    obtained with VecDuplicate() from the DM originating vectors.
2209 
2210 .keywords: DM, local-to-local, begin
2211 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2212 
2213 @*/
2214 PetscErrorCode  DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2215 {
2216   PetscErrorCode          ierr;
2217 
2218   PetscFunctionBegin;
2219   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2220   ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
2221   PetscFunctionReturn(0);
2222 }
2223 
2224 #undef __FUNCT__
2225 #define __FUNCT__ "DMLocalToLocalEnd"
2226 /*@
2227    DMLocalToLocalEnd - Maps from a local vector (including ghost points
2228    that contain irrelevant values) to another local vector where the ghost
2229    points in the second are set correctly. Must be preceded by DMLocalToLocalBegin().
2230 
2231    Neighbor-wise Collective on DM and Vec
2232 
2233    Input Parameters:
2234 +  da - the DM object
2235 .  g - the original local vector
2236 -  mode - one of INSERT_VALUES or ADD_VALUES
2237 
2238    Output Parameter:
2239 .  l  - the local vector with correct ghost values
2240 
2241    Level: intermediate
2242 
2243    Notes:
2244    The local vectors used here need not be the same as those
2245    obtained from DMCreateLocalVector(), BUT they
2246    must have the same parallel data layout; they could, for example, be
2247    obtained with VecDuplicate() from the DM originating vectors.
2248 
2249 .keywords: DM, local-to-local, end
2250 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2251 
2252 @*/
2253 PetscErrorCode  DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2254 {
2255   PetscErrorCode          ierr;
2256 
2257   PetscFunctionBegin;
2258   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2259   ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
2260   PetscFunctionReturn(0);
2261 }
2262 
2263 
2264 #undef __FUNCT__
2265 #define __FUNCT__ "DMCoarsen"
2266 /*@
2267     DMCoarsen - Coarsens a DM object
2268 
2269     Collective on DM
2270 
2271     Input Parameter:
2272 +   dm - the DM object
2273 -   comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
2274 
2275     Output Parameter:
2276 .   dmc - the coarsened DM
2277 
2278     Level: developer
2279 
2280 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2281 
2282 @*/
2283 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
2284 {
2285   PetscErrorCode    ierr;
2286   DMCoarsenHookLink link;
2287 
2288   PetscFunctionBegin;
2289   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2290   ierr = PetscLogEventBegin(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr);
2291   ierr                      = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr);
2292   if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced");
2293   ierr = DMSetCoarseDM(dm,*dmc);CHKERRQ(ierr);
2294   (*dmc)->ops->creatematrix = dm->ops->creatematrix;
2295   ierr                      = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr);
2296   (*dmc)->ctx               = dm->ctx;
2297   (*dmc)->levelup           = dm->levelup;
2298   (*dmc)->leveldown         = dm->leveldown + 1;
2299   ierr                      = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr);
2300   for (link=dm->coarsenhook; link; link=link->next) {
2301     if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);}
2302   }
2303   ierr = PetscLogEventEnd(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr);
2304   PetscFunctionReturn(0);
2305 }
2306 
2307 #undef __FUNCT__
2308 #define __FUNCT__ "DMCoarsenHookAdd"
2309 /*@C
2310    DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
2311 
2312    Logically Collective
2313 
2314    Input Arguments:
2315 +  fine - nonlinear solver context on which to run a hook when restricting to a coarser level
2316 .  coarsenhook - function to run when setting up a coarser level
2317 .  restricthook - function to run to update data on coarser levels (once per SNESSolve())
2318 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2319 
2320    Calling sequence of coarsenhook:
2321 $    coarsenhook(DM fine,DM coarse,void *ctx);
2322 
2323 +  fine - fine level DM
2324 .  coarse - coarse level DM to restrict problem to
2325 -  ctx - optional user-defined function context
2326 
2327    Calling sequence for restricthook:
2328 $    restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx)
2329 
2330 +  fine - fine level DM
2331 .  mrestrict - matrix restricting a fine-level solution to the coarse grid
2332 .  rscale - scaling vector for restriction
2333 .  inject - matrix restricting by injection
2334 .  coarse - coarse level DM to update
2335 -  ctx - optional user-defined function context
2336 
2337    Level: advanced
2338 
2339    Notes:
2340    This function is only needed if auxiliary data needs to be set up on coarse grids.
2341 
2342    If this function is called multiple times, the hooks will be run in the order they are added.
2343 
2344    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2345    extract the finest level information from its context (instead of from the SNES).
2346 
2347    This function is currently not available from Fortran.
2348 
2349 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2350 @*/
2351 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
2352 {
2353   PetscErrorCode    ierr;
2354   DMCoarsenHookLink link,*p;
2355 
2356   PetscFunctionBegin;
2357   PetscValidHeaderSpecific(fine,DM_CLASSID,1);
2358   for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2359   ierr               = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&link);CHKERRQ(ierr);
2360   link->coarsenhook  = coarsenhook;
2361   link->restricthook = restricthook;
2362   link->ctx          = ctx;
2363   link->next         = NULL;
2364   *p                 = link;
2365   PetscFunctionReturn(0);
2366 }
2367 
2368 #undef __FUNCT__
2369 #define __FUNCT__ "DMRestrict"
2370 /*@
2371    DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd()
2372 
2373    Collective if any hooks are
2374 
2375    Input Arguments:
2376 +  fine - finer DM to use as a base
2377 .  restrct - restriction matrix, apply using MatRestrict()
2378 .  inject - injection matrix, also use MatRestrict()
2379 -  coarse - coarer DM to update
2380 
2381    Level: developer
2382 
2383 .seealso: DMCoarsenHookAdd(), MatRestrict()
2384 @*/
2385 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse)
2386 {
2387   PetscErrorCode    ierr;
2388   DMCoarsenHookLink link;
2389 
2390   PetscFunctionBegin;
2391   for (link=fine->coarsenhook; link; link=link->next) {
2392     if (link->restricthook) {
2393       ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr);
2394     }
2395   }
2396   PetscFunctionReturn(0);
2397 }
2398 
2399 #undef __FUNCT__
2400 #define __FUNCT__ "DMSubDomainHookAdd"
2401 /*@C
2402    DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
2403 
2404    Logically Collective
2405 
2406    Input Arguments:
2407 +  global - global DM
2408 .  ddhook - function to run to pass data to the decomposition DM upon its creation
2409 .  restricthook - function to run to update data on block solve (at the beginning of the block solve)
2410 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2411 
2412 
2413    Calling sequence for ddhook:
2414 $    ddhook(DM global,DM block,void *ctx)
2415 
2416 +  global - global DM
2417 .  block  - block DM
2418 -  ctx - optional user-defined function context
2419 
2420    Calling sequence for restricthook:
2421 $    restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx)
2422 
2423 +  global - global DM
2424 .  out    - scatter to the outer (with ghost and overlap points) block vector
2425 .  in     - scatter to block vector values only owned locally
2426 .  block  - block DM
2427 -  ctx - optional user-defined function context
2428 
2429    Level: advanced
2430 
2431    Notes:
2432    This function is only needed if auxiliary data needs to be set up on subdomain DMs.
2433 
2434    If this function is called multiple times, the hooks will be run in the order they are added.
2435 
2436    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2437    extract the global information from its context (instead of from the SNES).
2438 
2439    This function is currently not available from Fortran.
2440 
2441 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2442 @*/
2443 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
2444 {
2445   PetscErrorCode      ierr;
2446   DMSubDomainHookLink link,*p;
2447 
2448   PetscFunctionBegin;
2449   PetscValidHeaderSpecific(global,DM_CLASSID,1);
2450   for (p=&global->subdomainhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2451   ierr               = PetscMalloc(sizeof(struct _DMSubDomainHookLink),&link);CHKERRQ(ierr);
2452   link->restricthook = restricthook;
2453   link->ddhook       = ddhook;
2454   link->ctx          = ctx;
2455   link->next         = NULL;
2456   *p                 = link;
2457   PetscFunctionReturn(0);
2458 }
2459 
2460 #undef __FUNCT__
2461 #define __FUNCT__ "DMSubDomainRestrict"
2462 /*@
2463    DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd()
2464 
2465    Collective if any hooks are
2466 
2467    Input Arguments:
2468 +  fine - finer DM to use as a base
2469 .  oscatter - scatter from domain global vector filling subdomain global vector with overlap
2470 .  gscatter - scatter from domain global vector filling subdomain local vector with ghosts
2471 -  coarse - coarer DM to update
2472 
2473    Level: developer
2474 
2475 .seealso: DMCoarsenHookAdd(), MatRestrict()
2476 @*/
2477 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm)
2478 {
2479   PetscErrorCode      ierr;
2480   DMSubDomainHookLink link;
2481 
2482   PetscFunctionBegin;
2483   for (link=global->subdomainhook; link; link=link->next) {
2484     if (link->restricthook) {
2485       ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr);
2486     }
2487   }
2488   PetscFunctionReturn(0);
2489 }
2490 
2491 #undef __FUNCT__
2492 #define __FUNCT__ "DMGetCoarsenLevel"
2493 /*@
2494     DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM.
2495 
2496     Not Collective
2497 
2498     Input Parameter:
2499 .   dm - the DM object
2500 
2501     Output Parameter:
2502 .   level - number of coarsenings
2503 
2504     Level: developer
2505 
2506 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2507 
2508 @*/
2509 PetscErrorCode  DMGetCoarsenLevel(DM dm,PetscInt *level)
2510 {
2511   PetscFunctionBegin;
2512   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2513   *level = dm->leveldown;
2514   PetscFunctionReturn(0);
2515 }
2516 
2517 
2518 
2519 #undef __FUNCT__
2520 #define __FUNCT__ "DMRefineHierarchy"
2521 /*@C
2522     DMRefineHierarchy - Refines a DM object, all levels at once
2523 
2524     Collective on DM
2525 
2526     Input Parameter:
2527 +   dm - the DM object
2528 -   nlevels - the number of levels of refinement
2529 
2530     Output Parameter:
2531 .   dmf - the refined DM hierarchy
2532 
2533     Level: developer
2534 
2535 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2536 
2537 @*/
2538 PetscErrorCode  DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
2539 {
2540   PetscErrorCode ierr;
2541 
2542   PetscFunctionBegin;
2543   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2544   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2545   if (nlevels == 0) PetscFunctionReturn(0);
2546   if (dm->ops->refinehierarchy) {
2547     ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr);
2548   } else if (dm->ops->refine) {
2549     PetscInt i;
2550 
2551     ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr);
2552     for (i=1; i<nlevels; i++) {
2553       ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr);
2554     }
2555   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
2556   PetscFunctionReturn(0);
2557 }
2558 
2559 #undef __FUNCT__
2560 #define __FUNCT__ "DMCoarsenHierarchy"
2561 /*@C
2562     DMCoarsenHierarchy - Coarsens a DM object, all levels at once
2563 
2564     Collective on DM
2565 
2566     Input Parameter:
2567 +   dm - the DM object
2568 -   nlevels - the number of levels of coarsening
2569 
2570     Output Parameter:
2571 .   dmc - the coarsened DM hierarchy
2572 
2573     Level: developer
2574 
2575 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2576 
2577 @*/
2578 PetscErrorCode  DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
2579 {
2580   PetscErrorCode ierr;
2581 
2582   PetscFunctionBegin;
2583   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2584   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2585   if (nlevels == 0) PetscFunctionReturn(0);
2586   PetscValidPointer(dmc,3);
2587   if (dm->ops->coarsenhierarchy) {
2588     ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr);
2589   } else if (dm->ops->coarsen) {
2590     PetscInt i;
2591 
2592     ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr);
2593     for (i=1; i<nlevels; i++) {
2594       ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr);
2595     }
2596   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
2597   PetscFunctionReturn(0);
2598 }
2599 
2600 #undef __FUNCT__
2601 #define __FUNCT__ "DMCreateAggregates"
2602 /*@
2603    DMCreateAggregates - Gets the aggregates that map between
2604    grids associated with two DMs.
2605 
2606    Collective on DM
2607 
2608    Input Parameters:
2609 +  dmc - the coarse grid DM
2610 -  dmf - the fine grid DM
2611 
2612    Output Parameters:
2613 .  rest - the restriction matrix (transpose of the projection matrix)
2614 
2615    Level: intermediate
2616 
2617 .keywords: interpolation, restriction, multigrid
2618 
2619 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation()
2620 @*/
2621 PetscErrorCode  DMCreateAggregates(DM dmc, DM dmf, Mat *rest)
2622 {
2623   PetscErrorCode ierr;
2624 
2625   PetscFunctionBegin;
2626   PetscValidHeaderSpecific(dmc,DM_CLASSID,1);
2627   PetscValidHeaderSpecific(dmf,DM_CLASSID,2);
2628   ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr);
2629   PetscFunctionReturn(0);
2630 }
2631 
2632 #undef __FUNCT__
2633 #define __FUNCT__ "DMSetApplicationContextDestroy"
2634 /*@C
2635     DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed
2636 
2637     Not Collective
2638 
2639     Input Parameters:
2640 +   dm - the DM object
2641 -   destroy - the destroy function
2642 
2643     Level: intermediate
2644 
2645 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2646 
2647 @*/
2648 PetscErrorCode  DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**))
2649 {
2650   PetscFunctionBegin;
2651   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2652   dm->ctxdestroy = destroy;
2653   PetscFunctionReturn(0);
2654 }
2655 
2656 #undef __FUNCT__
2657 #define __FUNCT__ "DMSetApplicationContext"
2658 /*@
2659     DMSetApplicationContext - Set a user context into a DM object
2660 
2661     Not Collective
2662 
2663     Input Parameters:
2664 +   dm - the DM object
2665 -   ctx - the user context
2666 
2667     Level: intermediate
2668 
2669 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2670 
2671 @*/
2672 PetscErrorCode  DMSetApplicationContext(DM dm,void *ctx)
2673 {
2674   PetscFunctionBegin;
2675   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2676   dm->ctx = ctx;
2677   PetscFunctionReturn(0);
2678 }
2679 
2680 #undef __FUNCT__
2681 #define __FUNCT__ "DMGetApplicationContext"
2682 /*@
2683     DMGetApplicationContext - Gets a user context from a DM object
2684 
2685     Not Collective
2686 
2687     Input Parameter:
2688 .   dm - the DM object
2689 
2690     Output Parameter:
2691 .   ctx - the user context
2692 
2693     Level: intermediate
2694 
2695 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2696 
2697 @*/
2698 PetscErrorCode  DMGetApplicationContext(DM dm,void *ctx)
2699 {
2700   PetscFunctionBegin;
2701   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2702   *(void**)ctx = dm->ctx;
2703   PetscFunctionReturn(0);
2704 }
2705 
2706 #undef __FUNCT__
2707 #define __FUNCT__ "DMSetVariableBounds"
2708 /*@C
2709     DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI.
2710 
2711     Logically Collective on DM
2712 
2713     Input Parameter:
2714 +   dm - the DM object
2715 -   f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set)
2716 
2717     Level: intermediate
2718 
2719 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(),
2720          DMSetJacobian()
2721 
2722 @*/
2723 PetscErrorCode  DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
2724 {
2725   PetscFunctionBegin;
2726   dm->ops->computevariablebounds = f;
2727   PetscFunctionReturn(0);
2728 }
2729 
2730 #undef __FUNCT__
2731 #define __FUNCT__ "DMHasVariableBounds"
2732 /*@
2733     DMHasVariableBounds - does the DM object have a variable bounds function?
2734 
2735     Not Collective
2736 
2737     Input Parameter:
2738 .   dm - the DM object to destroy
2739 
2740     Output Parameter:
2741 .   flg - PETSC_TRUE if the variable bounds function exists
2742 
2743     Level: developer
2744 
2745 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2746 
2747 @*/
2748 PetscErrorCode  DMHasVariableBounds(DM dm,PetscBool  *flg)
2749 {
2750   PetscFunctionBegin;
2751   *flg =  (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
2752   PetscFunctionReturn(0);
2753 }
2754 
2755 #undef __FUNCT__
2756 #define __FUNCT__ "DMComputeVariableBounds"
2757 /*@C
2758     DMComputeVariableBounds - compute variable bounds used by SNESVI.
2759 
2760     Logically Collective on DM
2761 
2762     Input Parameters:
2763 .   dm - the DM object
2764 
2765     Output parameters:
2766 +   xl - lower bound
2767 -   xu - upper bound
2768 
2769     Level: advanced
2770 
2771     Notes: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()
2772 
2773 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2774 
2775 @*/
2776 PetscErrorCode  DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
2777 {
2778   PetscErrorCode ierr;
2779 
2780   PetscFunctionBegin;
2781   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
2782   PetscValidHeaderSpecific(xu,VEC_CLASSID,2);
2783   if (dm->ops->computevariablebounds) {
2784     ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr);
2785   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds.");
2786   PetscFunctionReturn(0);
2787 }
2788 
2789 #undef __FUNCT__
2790 #define __FUNCT__ "DMHasColoring"
2791 /*@
2792     DMHasColoring - does the DM object have a method of providing a coloring?
2793 
2794     Not Collective
2795 
2796     Input Parameter:
2797 .   dm - the DM object
2798 
2799     Output Parameter:
2800 .   flg - PETSC_TRUE if the DM has facilities for DMCreateColoring().
2801 
2802     Level: developer
2803 
2804 .seealso DMHasFunction(), DMCreateColoring()
2805 
2806 @*/
2807 PetscErrorCode  DMHasColoring(DM dm,PetscBool  *flg)
2808 {
2809   PetscFunctionBegin;
2810   *flg =  (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
2811   PetscFunctionReturn(0);
2812 }
2813 
2814 #undef  __FUNCT__
2815 #define __FUNCT__ "DMSetVec"
2816 /*@C
2817     DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear.
2818 
2819     Collective on DM
2820 
2821     Input Parameter:
2822 +   dm - the DM object
2823 -   x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems.
2824 
2825     Level: developer
2826 
2827 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2828 
2829 @*/
2830 PetscErrorCode  DMSetVec(DM dm,Vec x)
2831 {
2832   PetscErrorCode ierr;
2833 
2834   PetscFunctionBegin;
2835   if (x) {
2836     if (!dm->x) {
2837       ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr);
2838     }
2839     ierr = VecCopy(x,dm->x);CHKERRQ(ierr);
2840   } else if (dm->x) {
2841     ierr = VecDestroy(&dm->x);CHKERRQ(ierr);
2842   }
2843   PetscFunctionReturn(0);
2844 }
2845 
2846 PetscFunctionList DMList              = NULL;
2847 PetscBool         DMRegisterAllCalled = PETSC_FALSE;
2848 
2849 #undef __FUNCT__
2850 #define __FUNCT__ "DMSetType"
2851 /*@C
2852   DMSetType - Builds a DM, for a particular DM implementation.
2853 
2854   Collective on DM
2855 
2856   Input Parameters:
2857 + dm     - The DM object
2858 - method - The name of the DM type
2859 
2860   Options Database Key:
2861 . -dm_type <type> - Sets the DM type; use -help for a list of available types
2862 
2863   Notes:
2864   See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).
2865 
2866   Level: intermediate
2867 
2868 .keywords: DM, set, type
2869 .seealso: DMGetType(), DMCreate()
2870 @*/
2871 PetscErrorCode  DMSetType(DM dm, DMType method)
2872 {
2873   PetscErrorCode (*r)(DM);
2874   PetscBool      match;
2875   PetscErrorCode ierr;
2876 
2877   PetscFunctionBegin;
2878   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
2879   ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr);
2880   if (match) PetscFunctionReturn(0);
2881 
2882   ierr = DMRegisterAll();CHKERRQ(ierr);
2883   ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr);
2884   if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
2885 
2886   if (dm->ops->destroy) {
2887     ierr             = (*dm->ops->destroy)(dm);CHKERRQ(ierr);
2888     dm->ops->destroy = NULL;
2889   }
2890   ierr = (*r)(dm);CHKERRQ(ierr);
2891   ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr);
2892   PetscFunctionReturn(0);
2893 }
2894 
2895 #undef __FUNCT__
2896 #define __FUNCT__ "DMGetType"
2897 /*@C
2898   DMGetType - Gets the DM type name (as a string) from the DM.
2899 
2900   Not Collective
2901 
2902   Input Parameter:
2903 . dm  - The DM
2904 
2905   Output Parameter:
2906 . type - The DM type name
2907 
2908   Level: intermediate
2909 
2910 .keywords: DM, get, type, name
2911 .seealso: DMSetType(), DMCreate()
2912 @*/
2913 PetscErrorCode  DMGetType(DM dm, DMType *type)
2914 {
2915   PetscErrorCode ierr;
2916 
2917   PetscFunctionBegin;
2918   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
2919   PetscValidPointer(type,2);
2920   ierr = DMRegisterAll();CHKERRQ(ierr);
2921   *type = ((PetscObject)dm)->type_name;
2922   PetscFunctionReturn(0);
2923 }
2924 
2925 #undef __FUNCT__
2926 #define __FUNCT__ "DMConvert"
2927 /*@C
2928   DMConvert - Converts a DM to another DM, either of the same or different type.
2929 
2930   Collective on DM
2931 
2932   Input Parameters:
2933 + dm - the DM
2934 - newtype - new DM type (use "same" for the same type)
2935 
2936   Output Parameter:
2937 . M - pointer to new DM
2938 
2939   Notes:
2940   Cannot be used to convert a sequential DM to parallel or parallel to sequential,
2941   the MPI communicator of the generated DM is always the same as the communicator
2942   of the input DM.
2943 
2944   Level: intermediate
2945 
2946 .seealso: DMCreate()
2947 @*/
2948 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
2949 {
2950   DM             B;
2951   char           convname[256];
2952   PetscBool      sametype, issame;
2953   PetscErrorCode ierr;
2954 
2955   PetscFunctionBegin;
2956   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2957   PetscValidType(dm,1);
2958   PetscValidPointer(M,3);
2959   ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr);
2960   ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr);
2961   {
2962     PetscErrorCode (*conv)(DM, DMType, DM*) = NULL;
2963 
2964     /*
2965        Order of precedence:
2966        1) See if a specialized converter is known to the current DM.
2967        2) See if a specialized converter is known to the desired DM class.
2968        3) See if a good general converter is registered for the desired class
2969        4) See if a good general converter is known for the current matrix.
2970        5) Use a really basic converter.
2971     */
2972 
2973     /* 1) See if a specialized converter is known to the current DM and the desired class */
2974     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
2975     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
2976     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
2977     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
2978     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
2979     ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr);
2980     if (conv) goto foundconv;
2981 
2982     /* 2)  See if a specialized converter is known to the desired DM class. */
2983     ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr);
2984     ierr = DMSetType(B, newtype);CHKERRQ(ierr);
2985     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
2986     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
2987     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
2988     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
2989     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
2990     ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr);
2991     if (conv) {
2992       ierr = DMDestroy(&B);CHKERRQ(ierr);
2993       goto foundconv;
2994     }
2995 
2996 #if 0
2997     /* 3) See if a good general converter is registered for the desired class */
2998     conv = B->ops->convertfrom;
2999     ierr = DMDestroy(&B);CHKERRQ(ierr);
3000     if (conv) goto foundconv;
3001 
3002     /* 4) See if a good general converter is known for the current matrix */
3003     if (dm->ops->convert) {
3004       conv = dm->ops->convert;
3005     }
3006     if (conv) goto foundconv;
3007 #endif
3008 
3009     /* 5) Use a really basic converter. */
3010     SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);
3011 
3012 foundconv:
3013     ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
3014     ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr);
3015     /* Things that are independent of DM type: We should consult DMClone() here */
3016     if (dm->maxCell) {
3017       const PetscReal *maxCell, *L;
3018       const DMBoundaryType *bd;
3019       ierr = DMGetPeriodicity(dm, &maxCell, &L, &bd);CHKERRQ(ierr);
3020       ierr = DMSetPeriodicity(*M,  maxCell,  L,  bd);CHKERRQ(ierr);
3021     }
3022     ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
3023   }
3024   ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr);
3025   PetscFunctionReturn(0);
3026 }
3027 
3028 /*--------------------------------------------------------------------------------------------------------------------*/
3029 
3030 #undef __FUNCT__
3031 #define __FUNCT__ "DMRegister"
3032 /*@C
3033   DMRegister -  Adds a new DM component implementation
3034 
3035   Not Collective
3036 
3037   Input Parameters:
3038 + name        - The name of a new user-defined creation routine
3039 - create_func - The creation routine itself
3040 
3041   Notes:
3042   DMRegister() may be called multiple times to add several user-defined DMs
3043 
3044 
3045   Sample usage:
3046 .vb
3047     DMRegister("my_da", MyDMCreate);
3048 .ve
3049 
3050   Then, your DM type can be chosen with the procedural interface via
3051 .vb
3052     DMCreate(MPI_Comm, DM *);
3053     DMSetType(DM,"my_da");
3054 .ve
3055    or at runtime via the option
3056 .vb
3057     -da_type my_da
3058 .ve
3059 
3060   Level: advanced
3061 
3062 .keywords: DM, register
3063 .seealso: DMRegisterAll(), DMRegisterDestroy()
3064 
3065 @*/
3066 PetscErrorCode  DMRegister(const char sname[],PetscErrorCode (*function)(DM))
3067 {
3068   PetscErrorCode ierr;
3069 
3070   PetscFunctionBegin;
3071   ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr);
3072   PetscFunctionReturn(0);
3073 }
3074 
3075 #undef __FUNCT__
3076 #define __FUNCT__ "DMLoad"
3077 /*@C
3078   DMLoad - Loads a DM that has been stored in binary  with DMView().
3079 
3080   Collective on PetscViewer
3081 
3082   Input Parameters:
3083 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
3084            some related function before a call to DMLoad().
3085 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
3086            HDF5 file viewer, obtained from PetscViewerHDF5Open()
3087 
3088    Level: intermediate
3089 
3090   Notes:
3091    The type is determined by the data in the file, any type set into the DM before this call is ignored.
3092 
3093   Notes for advanced users:
3094   Most users should not need to know the details of the binary storage
3095   format, since DMLoad() and DMView() completely hide these details.
3096   But for anyone who's interested, the standard binary matrix storage
3097   format is
3098 .vb
3099      has not yet been determined
3100 .ve
3101 
3102 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad()
3103 @*/
3104 PetscErrorCode  DMLoad(DM newdm, PetscViewer viewer)
3105 {
3106   PetscBool      isbinary, ishdf5;
3107   PetscErrorCode ierr;
3108 
3109   PetscFunctionBegin;
3110   PetscValidHeaderSpecific(newdm,DM_CLASSID,1);
3111   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
3112   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
3113   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
3114   if (isbinary) {
3115     PetscInt classid;
3116     char     type[256];
3117 
3118     ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr);
3119     if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid);
3120     ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr);
3121     ierr = DMSetType(newdm, type);CHKERRQ(ierr);
3122     if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);}
3123   } else if (ishdf5) {
3124     if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);}
3125   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
3126   PetscFunctionReturn(0);
3127 }
3128 
3129 /******************************** FEM Support **********************************/
3130 
3131 #undef __FUNCT__
3132 #define __FUNCT__ "DMPrintCellVector"
3133 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
3134 {
3135   PetscInt       f;
3136   PetscErrorCode ierr;
3137 
3138   PetscFunctionBegin;
3139   ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
3140   for (f = 0; f < len; ++f) {
3141     ierr = PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr);
3142   }
3143   PetscFunctionReturn(0);
3144 }
3145 
3146 #undef __FUNCT__
3147 #define __FUNCT__ "DMPrintCellMatrix"
3148 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
3149 {
3150   PetscInt       f, g;
3151   PetscErrorCode ierr;
3152 
3153   PetscFunctionBegin;
3154   ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
3155   for (f = 0; f < rows; ++f) {
3156     ierr = PetscPrintf(PETSC_COMM_SELF, "  |");CHKERRQ(ierr);
3157     for (g = 0; g < cols; ++g) {
3158       ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr);
3159     }
3160     ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr);
3161   }
3162   PetscFunctionReturn(0);
3163 }
3164 
3165 #undef __FUNCT__
3166 #define __FUNCT__ "DMPrintLocalVec"
3167 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
3168 {
3169   PetscMPIInt    rank, numProcs;
3170   PetscInt       p;
3171   PetscErrorCode ierr;
3172 
3173   PetscFunctionBegin;
3174   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr);
3175   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr);
3176   ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "%s:\n", name);CHKERRQ(ierr);
3177   for (p = 0; p < numProcs; ++p) {
3178     if (p == rank) {
3179       Vec x;
3180 
3181       ierr = VecDuplicate(X, &x);CHKERRQ(ierr);
3182       ierr = VecCopy(X, x);CHKERRQ(ierr);
3183       ierr = VecChop(x, tol);CHKERRQ(ierr);
3184       ierr = VecView(x, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
3185       ierr = VecDestroy(&x);CHKERRQ(ierr);
3186       ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
3187     }
3188     ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr);
3189   }
3190   PetscFunctionReturn(0);
3191 }
3192 
3193 #undef __FUNCT__
3194 #define __FUNCT__ "DMGetDefaultSection"
3195 /*@
3196   DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM.
3197 
3198   Input Parameter:
3199 . dm - The DM
3200 
3201   Output Parameter:
3202 . section - The PetscSection
3203 
3204   Level: intermediate
3205 
3206   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3207 
3208 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
3209 @*/
3210 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section)
3211 {
3212   PetscErrorCode ierr;
3213 
3214   PetscFunctionBegin;
3215   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3216   PetscValidPointer(section, 2);
3217   if (!dm->defaultSection && dm->ops->createdefaultsection) {
3218     ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr);
3219     if (dm->defaultSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);}
3220   }
3221   *section = dm->defaultSection;
3222   PetscFunctionReturn(0);
3223 }
3224 
3225 #undef __FUNCT__
3226 #define __FUNCT__ "DMSetDefaultSection"
3227 /*@
3228   DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM.
3229 
3230   Input Parameters:
3231 + dm - The DM
3232 - section - The PetscSection
3233 
3234   Level: intermediate
3235 
3236   Note: Any existing Section will be destroyed
3237 
3238 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
3239 @*/
3240 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section)
3241 {
3242   PetscInt       numFields = 0;
3243   PetscInt       f;
3244   PetscErrorCode ierr;
3245 
3246   PetscFunctionBegin;
3247   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3248   if (section) {
3249     PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
3250     ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
3251   }
3252   ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr);
3253   dm->defaultSection = section;
3254   if (section) {ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);}
3255   if (numFields) {
3256     ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr);
3257     for (f = 0; f < numFields; ++f) {
3258       PetscObject disc;
3259       const char *name;
3260 
3261       ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr);
3262       ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr);
3263       ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr);
3264     }
3265   }
3266   /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */
3267   ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr);
3268   PetscFunctionReturn(0);
3269 }
3270 
3271 #undef __FUNCT__
3272 #define __FUNCT__ "DMGetDefaultConstraints"
3273 /*@
3274   DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation.
3275 
3276   not collective
3277 
3278   Input Parameter:
3279 . dm - The DM
3280 
3281   Output Parameter:
3282 + 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.
3283 - 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.
3284 
3285   Level: advanced
3286 
3287   Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat.
3288 
3289 .seealso: DMSetDefaultConstraints()
3290 @*/
3291 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat)
3292 {
3293   PetscErrorCode ierr;
3294 
3295   PetscFunctionBegin;
3296   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3297   if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);}
3298   if (section) {*section = dm->defaultConstraintSection;}
3299   if (mat) {*mat = dm->defaultConstraintMat;}
3300   PetscFunctionReturn(0);
3301 }
3302 
3303 #undef __FUNCT__
3304 #define __FUNCT__ "DMSetDefaultConstraints"
3305 /*@
3306   DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation.
3307 
3308   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().
3309 
3310   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.
3311 
3312   collective on dm
3313 
3314   Input Parameters:
3315 + dm - The DM
3316 + 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).
3317 - 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).
3318 
3319   Level: advanced
3320 
3321   Note: This increments the references of the PetscSection and the Mat, so they user can destroy them
3322 
3323 .seealso: DMGetDefaultConstraints()
3324 @*/
3325 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat)
3326 {
3327   PetscMPIInt result;
3328   PetscErrorCode ierr;
3329 
3330   PetscFunctionBegin;
3331   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3332   if (section) {
3333     PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
3334     ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr);
3335     if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator");
3336   }
3337   if (mat) {
3338     PetscValidHeaderSpecific(mat,MAT_CLASSID,3);
3339     ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr);
3340     if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator");
3341   }
3342   ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
3343   ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr);
3344   dm->defaultConstraintSection = section;
3345   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
3346   ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr);
3347   dm->defaultConstraintMat = mat;
3348   PetscFunctionReturn(0);
3349 }
3350 
3351 #ifdef PETSC_USE_DEBUG
3352 #undef __FUNCT__
3353 #define __FUNCT__ "DMDefaultSectionCheckConsistency_Internal"
3354 /*
3355   DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections.
3356 
3357   Input Parameters:
3358 + dm - The DM
3359 . localSection - PetscSection describing the local data layout
3360 - globalSection - PetscSection describing the global data layout
3361 
3362   Level: intermediate
3363 
3364 .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3365 */
3366 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
3367 {
3368   MPI_Comm        comm;
3369   PetscLayout     layout;
3370   const PetscInt *ranges;
3371   PetscInt        pStart, pEnd, p, nroots;
3372   PetscMPIInt     size, rank;
3373   PetscBool       valid = PETSC_TRUE, gvalid;
3374   PetscErrorCode  ierr;
3375 
3376   PetscFunctionBegin;
3377   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
3378   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3379   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
3380   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3381   ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr);
3382   ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr);
3383   ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
3384   ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
3385   ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr);
3386   ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
3387   ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
3388   for (p = pStart; p < pEnd; ++p) {
3389     PetscInt       dof, cdof, off, gdof, gcdof, goff, gsize, d;
3390 
3391     ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr);
3392     ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr);
3393     ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr);
3394     ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3395     ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3396     ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr);
3397     if (!gdof) continue; /* Censored point */
3398     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;}
3399     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;}
3400     if (gdof < 0) {
3401       gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3402       for (d = 0; d < gsize; ++d) {
3403         PetscInt offset = -(goff+1) + d, r;
3404 
3405         ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr);
3406         if (r < 0) r = -(r+2);
3407         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;}
3408       }
3409     }
3410   }
3411   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
3412   ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
3413   ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr);
3414   if (!gvalid) {
3415     ierr = DMView(dm, NULL);CHKERRQ(ierr);
3416     SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
3417   }
3418   PetscFunctionReturn(0);
3419 }
3420 #endif
3421 
3422 #undef __FUNCT__
3423 #define __FUNCT__ "DMGetDefaultGlobalSection"
3424 /*@
3425   DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM.
3426 
3427   Collective on DM
3428 
3429   Input Parameter:
3430 . dm - The DM
3431 
3432   Output Parameter:
3433 . section - The PetscSection
3434 
3435   Level: intermediate
3436 
3437   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3438 
3439 .seealso: DMSetDefaultSection(), DMGetDefaultSection()
3440 @*/
3441 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section)
3442 {
3443   PetscErrorCode ierr;
3444 
3445   PetscFunctionBegin;
3446   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3447   PetscValidPointer(section, 2);
3448   if (!dm->defaultGlobalSection) {
3449     PetscSection s;
3450 
3451     ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
3452     if (!s)  SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
3453     if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection");
3454     ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr);
3455     ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr);
3456     ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr);
3457     ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");CHKERRQ(ierr);
3458   }
3459   *section = dm->defaultGlobalSection;
3460   PetscFunctionReturn(0);
3461 }
3462 
3463 #undef __FUNCT__
3464 #define __FUNCT__ "DMSetDefaultGlobalSection"
3465 /*@
3466   DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM.
3467 
3468   Input Parameters:
3469 + dm - The DM
3470 - section - The PetscSection, or NULL
3471 
3472   Level: intermediate
3473 
3474   Note: Any existing Section will be destroyed
3475 
3476 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection()
3477 @*/
3478 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section)
3479 {
3480   PetscErrorCode ierr;
3481 
3482   PetscFunctionBegin;
3483   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3484   if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
3485   ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
3486   ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr);
3487   dm->defaultGlobalSection = section;
3488 #ifdef PETSC_USE_DEBUG
3489   if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);}
3490 #endif
3491   PetscFunctionReturn(0);
3492 }
3493 
3494 #undef __FUNCT__
3495 #define __FUNCT__ "DMGetDefaultSF"
3496 /*@
3497   DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set,
3498   it is created from the default PetscSection layouts in the DM.
3499 
3500   Input Parameter:
3501 . dm - The DM
3502 
3503   Output Parameter:
3504 . sf - The PetscSF
3505 
3506   Level: intermediate
3507 
3508   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3509 
3510 .seealso: DMSetDefaultSF(), DMCreateDefaultSF()
3511 @*/
3512 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf)
3513 {
3514   PetscInt       nroots;
3515   PetscErrorCode ierr;
3516 
3517   PetscFunctionBegin;
3518   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3519   PetscValidPointer(sf, 2);
3520   ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
3521   if (nroots < 0) {
3522     PetscSection section, gSection;
3523 
3524     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
3525     if (section) {
3526       ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr);
3527       ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr);
3528     } else {
3529       *sf = NULL;
3530       PetscFunctionReturn(0);
3531     }
3532   }
3533   *sf = dm->defaultSF;
3534   PetscFunctionReturn(0);
3535 }
3536 
3537 #undef __FUNCT__
3538 #define __FUNCT__ "DMSetDefaultSF"
3539 /*@
3540   DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM
3541 
3542   Input Parameters:
3543 + dm - The DM
3544 - sf - The PetscSF
3545 
3546   Level: intermediate
3547 
3548   Note: Any previous SF is destroyed
3549 
3550 .seealso: DMGetDefaultSF(), DMCreateDefaultSF()
3551 @*/
3552 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf)
3553 {
3554   PetscErrorCode ierr;
3555 
3556   PetscFunctionBegin;
3557   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3558   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
3559   ierr          = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr);
3560   dm->defaultSF = sf;
3561   PetscFunctionReturn(0);
3562 }
3563 
3564 #undef __FUNCT__
3565 #define __FUNCT__ "DMCreateDefaultSF"
3566 /*@C
3567   DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections
3568   describing the data layout.
3569 
3570   Input Parameters:
3571 + dm - The DM
3572 . localSection - PetscSection describing the local data layout
3573 - globalSection - PetscSection describing the global data layout
3574 
3575   Level: intermediate
3576 
3577 .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3578 @*/
3579 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection)
3580 {
3581   MPI_Comm       comm;
3582   PetscLayout    layout;
3583   const PetscInt *ranges;
3584   PetscInt       *local;
3585   PetscSFNode    *remote;
3586   PetscInt       pStart, pEnd, p, nroots, nleaves = 0, l;
3587   PetscMPIInt    size, rank;
3588   PetscErrorCode ierr;
3589 
3590   PetscFunctionBegin;
3591   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
3592   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3593   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
3594   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3595   ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr);
3596   ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr);
3597   ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
3598   ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
3599   ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr);
3600   ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
3601   ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
3602   for (p = pStart; p < pEnd; ++p) {
3603     PetscInt gdof, gcdof;
3604 
3605     ierr     = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3606     ierr     = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3607     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));
3608     nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3609   }
3610   ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr);
3611   ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr);
3612   for (p = pStart, l = 0; p < pEnd; ++p) {
3613     const PetscInt *cind;
3614     PetscInt       dof, cdof, off, gdof, gcdof, goff, gsize, d, c;
3615 
3616     ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr);
3617     ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr);
3618     ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr);
3619     ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr);
3620     ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3621     ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3622     ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr);
3623     if (!gdof) continue; /* Censored point */
3624     gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3625     if (gsize != dof-cdof) {
3626       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);
3627       cdof = 0; /* Ignore constraints */
3628     }
3629     for (d = 0, c = 0; d < dof; ++d) {
3630       if ((c < cdof) && (cind[c] == d)) {++c; continue;}
3631       local[l+d-c] = off+d;
3632     }
3633     if (gdof < 0) {
3634       for (d = 0; d < gsize; ++d, ++l) {
3635         PetscInt offset = -(goff+1) + d, r;
3636 
3637         ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr);
3638         if (r < 0) r = -(r+2);
3639         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);
3640         remote[l].rank  = r;
3641         remote[l].index = offset - ranges[r];
3642       }
3643     } else {
3644       for (d = 0; d < gsize; ++d, ++l) {
3645         remote[l].rank  = rank;
3646         remote[l].index = goff+d - ranges[rank];
3647       }
3648     }
3649   }
3650   if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves);
3651   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
3652   ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr);
3653   PetscFunctionReturn(0);
3654 }
3655 
3656 #undef __FUNCT__
3657 #define __FUNCT__ "DMGetPointSF"
3658 /*@
3659   DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM.
3660 
3661   Input Parameter:
3662 . dm - The DM
3663 
3664   Output Parameter:
3665 . sf - The PetscSF
3666 
3667   Level: intermediate
3668 
3669   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3670 
3671 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3672 @*/
3673 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
3674 {
3675   PetscFunctionBegin;
3676   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3677   PetscValidPointer(sf, 2);
3678   *sf = dm->sf;
3679   PetscFunctionReturn(0);
3680 }
3681 
3682 #undef __FUNCT__
3683 #define __FUNCT__ "DMSetPointSF"
3684 /*@
3685   DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM.
3686 
3687   Input Parameters:
3688 + dm - The DM
3689 - sf - The PetscSF
3690 
3691   Level: intermediate
3692 
3693 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3694 @*/
3695 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
3696 {
3697   PetscErrorCode ierr;
3698 
3699   PetscFunctionBegin;
3700   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3701   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
3702   ierr   = PetscSFDestroy(&dm->sf);CHKERRQ(ierr);
3703   ierr   = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr);
3704   dm->sf = sf;
3705   PetscFunctionReturn(0);
3706 }
3707 
3708 #undef __FUNCT__
3709 #define __FUNCT__ "DMGetDS"
3710 /*@
3711   DMGetDS - Get the PetscDS
3712 
3713   Input Parameter:
3714 . dm - The DM
3715 
3716   Output Parameter:
3717 . prob - The PetscDS
3718 
3719   Level: developer
3720 
3721 .seealso: DMSetDS()
3722 @*/
3723 PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
3724 {
3725   PetscFunctionBegin;
3726   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3727   PetscValidPointer(prob, 2);
3728   *prob = dm->prob;
3729   PetscFunctionReturn(0);
3730 }
3731 
3732 #undef __FUNCT__
3733 #define __FUNCT__ "DMSetDS"
3734 /*@
3735   DMSetDS - Set the PetscDS
3736 
3737   Input Parameters:
3738 + dm - The DM
3739 - prob - The PetscDS
3740 
3741   Level: developer
3742 
3743 .seealso: DMGetDS()
3744 @*/
3745 PetscErrorCode DMSetDS(DM dm, PetscDS prob)
3746 {
3747   PetscErrorCode ierr;
3748 
3749   PetscFunctionBegin;
3750   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3751   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2);
3752   ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr);
3753   dm->prob = prob;
3754   ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr);
3755   PetscFunctionReturn(0);
3756 }
3757 
3758 #undef __FUNCT__
3759 #define __FUNCT__ "DMGetNumFields"
3760 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
3761 {
3762   PetscErrorCode ierr;
3763 
3764   PetscFunctionBegin;
3765   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3766   ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr);
3767   PetscFunctionReturn(0);
3768 }
3769 
3770 #undef __FUNCT__
3771 #define __FUNCT__ "DMSetNumFields"
3772 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
3773 {
3774   PetscInt       Nf, f;
3775   PetscErrorCode ierr;
3776 
3777   PetscFunctionBegin;
3778   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3779   ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr);
3780   for (f = Nf; f < numFields; ++f) {
3781     PetscContainer obj;
3782 
3783     ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr);
3784     ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr);
3785     ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr);
3786   }
3787   PetscFunctionReturn(0);
3788 }
3789 
3790 #undef __FUNCT__
3791 #define __FUNCT__ "DMGetField"
3792 /*@
3793   DMGetField - Return the discretization object for a given DM field
3794 
3795   Not collective
3796 
3797   Input Parameters:
3798 + dm - The DM
3799 - f  - The field number
3800 
3801   Output Parameter:
3802 . field - The discretization object
3803 
3804   Level: developer
3805 
3806 .seealso: DMSetField()
3807 @*/
3808 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field)
3809 {
3810   PetscErrorCode ierr;
3811 
3812   PetscFunctionBegin;
3813   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3814   ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr);
3815   PetscFunctionReturn(0);
3816 }
3817 
3818 #undef __FUNCT__
3819 #define __FUNCT__ "DMSetField"
3820 /*@
3821   DMSetField - Set the discretization object for a given DM field
3822 
3823   Logically collective on DM
3824 
3825   Input Parameters:
3826 + dm - The DM
3827 . f  - The field number
3828 - field - The discretization object
3829 
3830   Level: developer
3831 
3832 .seealso: DMGetField()
3833 @*/
3834 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field)
3835 {
3836   PetscErrorCode ierr;
3837 
3838   PetscFunctionBegin;
3839   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3840   ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr);
3841   PetscFunctionReturn(0);
3842 }
3843 
3844 #undef __FUNCT__
3845 #define __FUNCT__ "DMRestrictHook_Coordinates"
3846 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx)
3847 {
3848   DM dm_coord,dmc_coord;
3849   PetscErrorCode ierr;
3850   Vec coords,ccoords;
3851   Mat inject;
3852   PetscFunctionBegin;
3853   ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr);
3854   ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr);
3855   ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
3856   ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr);
3857   if (coords && !ccoords) {
3858     ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr);
3859     ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr);
3860     ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr);
3861     ierr = MatDestroy(&inject);CHKERRQ(ierr);
3862     ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr);
3863     ierr = VecDestroy(&ccoords);CHKERRQ(ierr);
3864   }
3865   PetscFunctionReturn(0);
3866 }
3867 
3868 #undef __FUNCT__
3869 #define __FUNCT__ "DMSubDomainHook_Coordinates"
3870 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx)
3871 {
3872   DM dm_coord,subdm_coord;
3873   PetscErrorCode ierr;
3874   Vec coords,ccoords,clcoords;
3875   VecScatter *scat_i,*scat_g;
3876   PetscFunctionBegin;
3877   ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr);
3878   ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr);
3879   ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
3880   ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr);
3881   if (coords && !ccoords) {
3882     ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr);
3883     ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr);
3884     ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr);
3885     ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr);
3886     ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3887     ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3888     ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3889     ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3890     ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr);
3891     ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr);
3892     ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr);
3893     ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr);
3894     ierr = VecDestroy(&ccoords);CHKERRQ(ierr);
3895     ierr = VecDestroy(&clcoords);CHKERRQ(ierr);
3896     ierr = PetscFree(scat_i);CHKERRQ(ierr);
3897     ierr = PetscFree(scat_g);CHKERRQ(ierr);
3898   }
3899   PetscFunctionReturn(0);
3900 }
3901 
3902 #undef __FUNCT__
3903 #define __FUNCT__ "DMGetDimension"
3904 /*@
3905   DMGetDimension - Return the topological dimension of the DM
3906 
3907   Not collective
3908 
3909   Input Parameter:
3910 . dm - The DM
3911 
3912   Output Parameter:
3913 . dim - The topological dimension
3914 
3915   Level: beginner
3916 
3917 .seealso: DMSetDimension(), DMCreate()
3918 @*/
3919 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
3920 {
3921   PetscFunctionBegin;
3922   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3923   PetscValidPointer(dim, 2);
3924   *dim = dm->dim;
3925   PetscFunctionReturn(0);
3926 }
3927 
3928 #undef __FUNCT__
3929 #define __FUNCT__ "DMSetDimension"
3930 /*@
3931   DMSetDimension - Set the topological dimension of the DM
3932 
3933   Collective on dm
3934 
3935   Input Parameters:
3936 + dm - The DM
3937 - dim - The topological dimension
3938 
3939   Level: beginner
3940 
3941 .seealso: DMGetDimension(), DMCreate()
3942 @*/
3943 PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
3944 {
3945   PetscFunctionBegin;
3946   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3947   PetscValidLogicalCollectiveInt(dm, dim, 2);
3948   dm->dim = dim;
3949   PetscFunctionReturn(0);
3950 }
3951 
3952 #undef __FUNCT__
3953 #define __FUNCT__ "DMGetDimPoints"
3954 /*@
3955   DMGetDimPoints - Get the half-open interval for all points of a given dimension
3956 
3957   Collective on DM
3958 
3959   Input Parameters:
3960 + dm - the DM
3961 - dim - the dimension
3962 
3963   Output Parameters:
3964 + pStart - The first point of the given dimension
3965 . pEnd - The first point following points of the given dimension
3966 
3967   Note:
3968   The points are vertices in the Hasse diagram encoding the topology. This is explained in
3969   http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme,
3970   then the interval is empty.
3971 
3972   Level: intermediate
3973 
3974 .keywords: point, Hasse Diagram, dimension
3975 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum()
3976 @*/
3977 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
3978 {
3979   PetscInt       d;
3980   PetscErrorCode ierr;
3981 
3982   PetscFunctionBegin;
3983   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3984   ierr = DMGetDimension(dm, &d);CHKERRQ(ierr);
3985   if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d);
3986   ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr);
3987   PetscFunctionReturn(0);
3988 }
3989 
3990 #undef __FUNCT__
3991 #define __FUNCT__ "DMSetCoordinates"
3992 /*@
3993   DMSetCoordinates - Sets into the DM a global vector that holds the coordinates
3994 
3995   Collective on DM
3996 
3997   Input Parameters:
3998 + dm - the DM
3999 - c - coordinate vector
4000 
4001   Note:
4002   The coordinates do include those for ghost points, which are in the local vector
4003 
4004   Level: intermediate
4005 
4006 .keywords: distributed array, get, corners, nodes, local indices, coordinates
4007 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM()
4008 @*/
4009 PetscErrorCode DMSetCoordinates(DM dm, Vec c)
4010 {
4011   PetscErrorCode ierr;
4012 
4013   PetscFunctionBegin;
4014   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4015   PetscValidHeaderSpecific(c,VEC_CLASSID,2);
4016   ierr            = PetscObjectReference((PetscObject) c);CHKERRQ(ierr);
4017   ierr            = VecDestroy(&dm->coordinates);CHKERRQ(ierr);
4018   dm->coordinates = c;
4019   ierr            = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr);
4020   ierr            = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr);
4021   ierr            = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr);
4022   PetscFunctionReturn(0);
4023 }
4024 
4025 #undef __FUNCT__
4026 #define __FUNCT__ "DMSetCoordinatesLocal"
4027 /*@
4028   DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates
4029 
4030   Collective on DM
4031 
4032    Input Parameters:
4033 +  dm - the DM
4034 -  c - coordinate vector
4035 
4036   Note:
4037   The coordinates of ghost points can be set using DMSetCoordinates()
4038   followed by DMGetCoordinatesLocal(). This is intended to enable the
4039   setting of ghost coordinates outside of the domain.
4040 
4041   Level: intermediate
4042 
4043 .keywords: distributed array, get, corners, nodes, local indices, coordinates
4044 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM()
4045 @*/
4046 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c)
4047 {
4048   PetscErrorCode ierr;
4049 
4050   PetscFunctionBegin;
4051   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4052   PetscValidHeaderSpecific(c,VEC_CLASSID,2);
4053   ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr);
4054   ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr);
4055 
4056   dm->coordinatesLocal = c;
4057 
4058   ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr);
4059   PetscFunctionReturn(0);
4060 }
4061 
4062 #undef __FUNCT__
4063 #define __FUNCT__ "DMGetCoordinates"
4064 /*@
4065   DMGetCoordinates - Gets a global vector with the coordinates associated with the DM.
4066 
4067   Not Collective
4068 
4069   Input Parameter:
4070 . dm - the DM
4071 
4072   Output Parameter:
4073 . c - global coordinate vector
4074 
4075   Note:
4076   This is a borrowed reference, so the user should NOT destroy this vector
4077 
4078   Each process has only the local coordinates (does NOT have the ghost coordinates).
4079 
4080   For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
4081   and (x_0,y_0,z_0,x_1,y_1,z_1...)
4082 
4083   Level: intermediate
4084 
4085 .keywords: distributed array, get, corners, nodes, local indices, coordinates
4086 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
4087 @*/
4088 PetscErrorCode DMGetCoordinates(DM dm, Vec *c)
4089 {
4090   PetscErrorCode ierr;
4091 
4092   PetscFunctionBegin;
4093   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4094   PetscValidPointer(c,2);
4095   if (!dm->coordinates && dm->coordinatesLocal) {
4096     DM cdm = NULL;
4097 
4098     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
4099     ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr);
4100     ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr);
4101     ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr);
4102     ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr);
4103   }
4104   *c = dm->coordinates;
4105   PetscFunctionReturn(0);
4106 }
4107 
4108 #undef __FUNCT__
4109 #define __FUNCT__ "DMGetCoordinatesLocal"
4110 /*@
4111   DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM.
4112 
4113   Collective on DM
4114 
4115   Input Parameter:
4116 . dm - the DM
4117 
4118   Output Parameter:
4119 . c - coordinate vector
4120 
4121   Note:
4122   This is a borrowed reference, so the user should NOT destroy this vector
4123 
4124   Each process has the local and ghost coordinates
4125 
4126   For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
4127   and (x_0,y_0,z_0,x_1,y_1,z_1...)
4128 
4129   Level: intermediate
4130 
4131 .keywords: distributed array, get, corners, nodes, local indices, coordinates
4132 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM()
4133 @*/
4134 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c)
4135 {
4136   PetscErrorCode ierr;
4137 
4138   PetscFunctionBegin;
4139   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4140   PetscValidPointer(c,2);
4141   if (!dm->coordinatesLocal && dm->coordinates) {
4142     DM cdm = NULL;
4143 
4144     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
4145     ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr);
4146     ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr);
4147     ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr);
4148     ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr);
4149   }
4150   *c = dm->coordinatesLocal;
4151   PetscFunctionReturn(0);
4152 }
4153 
4154 #undef __FUNCT__
4155 #define __FUNCT__ "DMGetCoordinateDM"
4156 /*@
4157   DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates
4158 
4159   Collective on DM
4160 
4161   Input Parameter:
4162 . dm - the DM
4163 
4164   Output Parameter:
4165 . cdm - coordinate DM
4166 
4167   Level: intermediate
4168 
4169 .keywords: distributed array, get, corners, nodes, local indices, coordinates
4170 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4171 @*/
4172 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm)
4173 {
4174   PetscErrorCode ierr;
4175 
4176   PetscFunctionBegin;
4177   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4178   PetscValidPointer(cdm,2);
4179   if (!dm->coordinateDM) {
4180     if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM");
4181     ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr);
4182   }
4183   *cdm = dm->coordinateDM;
4184   PetscFunctionReturn(0);
4185 }
4186 
4187 #undef __FUNCT__
4188 #define __FUNCT__ "DMSetCoordinateDM"
4189 /*@
4190   DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates
4191 
4192   Logically Collective on DM
4193 
4194   Input Parameters:
4195 + dm - the DM
4196 - cdm - coordinate DM
4197 
4198   Level: intermediate
4199 
4200 .keywords: distributed array, get, corners, nodes, local indices, coordinates
4201 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4202 @*/
4203 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm)
4204 {
4205   PetscErrorCode ierr;
4206 
4207   PetscFunctionBegin;
4208   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4209   PetscValidHeaderSpecific(cdm,DM_CLASSID,2);
4210   ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr);
4211   dm->coordinateDM = cdm;
4212   ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr);
4213   PetscFunctionReturn(0);
4214 }
4215 
4216 #undef __FUNCT__
4217 #define __FUNCT__ "DMGetCoordinateDim"
4218 /*@
4219   DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values.
4220 
4221   Not Collective
4222 
4223   Input Parameter:
4224 . dm - The DM object
4225 
4226   Output Parameter:
4227 . dim - The embedding dimension
4228 
4229   Level: intermediate
4230 
4231 .keywords: mesh, coordinates
4232 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
4233 @*/
4234 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim)
4235 {
4236   PetscFunctionBegin;
4237   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4238   PetscValidPointer(dim, 2);
4239   if (dm->dimEmbed == PETSC_DEFAULT) {
4240     dm->dimEmbed = dm->dim;
4241   }
4242   *dim = dm->dimEmbed;
4243   PetscFunctionReturn(0);
4244 }
4245 
4246 #undef __FUNCT__
4247 #define __FUNCT__ "DMSetCoordinateDim"
4248 /*@
4249   DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values.
4250 
4251   Not Collective
4252 
4253   Input Parameters:
4254 + dm  - The DM object
4255 - dim - The embedding dimension
4256 
4257   Level: intermediate
4258 
4259 .keywords: mesh, coordinates
4260 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
4261 @*/
4262 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim)
4263 {
4264   PetscFunctionBegin;
4265   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4266   dm->dimEmbed = dim;
4267   PetscFunctionReturn(0);
4268 }
4269 
4270 #undef __FUNCT__
4271 #define __FUNCT__ "DMGetCoordinateSection"
4272 /*@
4273   DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh.
4274 
4275   Not Collective
4276 
4277   Input Parameter:
4278 . dm - The DM object
4279 
4280   Output Parameter:
4281 . section - The PetscSection object
4282 
4283   Level: intermediate
4284 
4285 .keywords: mesh, coordinates
4286 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
4287 @*/
4288 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section)
4289 {
4290   DM             cdm;
4291   PetscErrorCode ierr;
4292 
4293   PetscFunctionBegin;
4294   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4295   PetscValidPointer(section, 2);
4296   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
4297   ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr);
4298   PetscFunctionReturn(0);
4299 }
4300 
4301 #undef __FUNCT__
4302 #define __FUNCT__ "DMSetCoordinateSection"
4303 /*@
4304   DMSetCoordinateSection - Set the layout of coordinate values over the mesh.
4305 
4306   Not Collective
4307 
4308   Input Parameters:
4309 + dm      - The DM object
4310 . dim     - The embedding dimension, or PETSC_DETERMINE
4311 - section - The PetscSection object
4312 
4313   Level: intermediate
4314 
4315 .keywords: mesh, coordinates
4316 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
4317 @*/
4318 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section)
4319 {
4320   DM             cdm;
4321   PetscErrorCode ierr;
4322 
4323   PetscFunctionBegin;
4324   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4325   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3);
4326   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
4327   ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr);
4328   if (dim == PETSC_DETERMINE) {
4329     PetscInt d = dim;
4330     PetscInt pStart, pEnd, vStart, vEnd, v, dd;
4331 
4332     ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
4333     ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
4334     pStart = PetscMax(vStart, pStart);
4335     pEnd   = PetscMin(vEnd, pEnd);
4336     for (v = pStart; v < pEnd; ++v) {
4337       ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr);
4338       if (dd) {d = dd; break;}
4339     }
4340     ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);
4341   }
4342   PetscFunctionReturn(0);
4343 }
4344 
4345 #undef __FUNCT__
4346 #define __FUNCT__ "DMGetPeriodicity"
4347 /*@C
4348   DMSetPeriodicity - Set the description of mesh periodicity
4349 
4350   Input Parameters:
4351 + dm      - The DM object
4352 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
4353 . L       - If we assume the mesh is a torus, this is the length of each coordinate
4354 - bd      - This describes the type of periodicity in each topological dimension
4355 
4356   Level: developer
4357 
4358 .seealso: DMGetPeriodicity()
4359 @*/
4360 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd)
4361 {
4362   PetscFunctionBegin;
4363   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4364   if (L)       *L       = dm->L;
4365   if (maxCell) *maxCell = dm->maxCell;
4366   if (bd)      *bd      = dm->bdtype;
4367   PetscFunctionReturn(0);
4368 }
4369 
4370 #undef __FUNCT__
4371 #define __FUNCT__ "DMSetPeriodicity"
4372 /*@C
4373   DMSetPeriodicity - Set the description of mesh periodicity
4374 
4375   Input Parameters:
4376 + dm      - The DM object
4377 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
4378 . L       - If we assume the mesh is a torus, this is the length of each coordinate
4379 - bd      - This describes the type of periodicity in each topological dimension
4380 
4381   Level: developer
4382 
4383 .seealso: DMGetPeriodicity()
4384 @*/
4385 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[])
4386 {
4387   PetscInt       dim, d;
4388   PetscErrorCode ierr;
4389 
4390   PetscFunctionBegin;
4391   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4392   PetscValidPointer(L,3);PetscValidPointer(maxCell,2);PetscValidPointer(bd,4);
4393   ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr);
4394   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
4395   ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr);
4396   for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];}
4397   PetscFunctionReturn(0);
4398 }
4399 
4400 #undef __FUNCT__
4401 #define __FUNCT__ "DMLocalizeCoordinate"
4402 /*@
4403   DMLocalizeCoordinate - If a mesh is periodic (a torus with lengths L_i, some of which can be infinite), project the coordinate onto [0, L_i) in each dimension.
4404 
4405   Input Parameters:
4406 + dm     - The DM
4407 - in     - The input coordinate point (dim numbers)
4408 
4409   Output Parameter:
4410 . out - The localized coordinate point
4411 
4412   Level: developer
4413 
4414 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate()
4415 @*/
4416 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscScalar out[])
4417 {
4418   PetscInt       dim, d;
4419   PetscErrorCode ierr;
4420 
4421   PetscFunctionBegin;
4422   ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr);
4423   if (!dm->maxCell) {
4424     for (d = 0; d < dim; ++d) out[d] = in[d];
4425   } else {
4426     for (d = 0; d < dim; ++d) {
4427       out[d] = in[d] - dm->L[d]*floor(PetscRealPart(in[d])/dm->L[d]);
4428     }
4429   }
4430   PetscFunctionReturn(0);
4431 }
4432 
4433 #undef __FUNCT__
4434 #define __FUNCT__ "DMLocalizeCoordinate_Internal"
4435 /*
4436   DMLocalizeCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer.
4437 
4438   Input Parameters:
4439 + dm     - The DM
4440 . dim    - The spatial dimension
4441 . anchor - The anchor point, the input point can be no more than maxCell away from it
4442 - in     - The input coordinate point (dim numbers)
4443 
4444   Output Parameter:
4445 . out - The localized coordinate point
4446 
4447   Level: developer
4448 
4449   Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell
4450 
4451 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate()
4452 */
4453 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
4454 {
4455   PetscInt d;
4456 
4457   PetscFunctionBegin;
4458   if (!dm->maxCell) {
4459     for (d = 0; d < dim; ++d) out[d] = in[d];
4460   } else {
4461     for (d = 0; d < dim; ++d) {
4462       if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) {
4463         out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
4464       } else {
4465         out[d] = in[d];
4466       }
4467     }
4468   }
4469   PetscFunctionReturn(0);
4470 }
4471 #undef __FUNCT__
4472 #define __FUNCT__ "DMLocalizeCoordinateReal_Internal"
4473 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[])
4474 {
4475   PetscInt d;
4476 
4477   PetscFunctionBegin;
4478   if (!dm->maxCell) {
4479     for (d = 0; d < dim; ++d) out[d] = in[d];
4480   } else {
4481     for (d = 0; d < dim; ++d) {
4482       if (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d]) {
4483         out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d];
4484       } else {
4485         out[d] = in[d];
4486       }
4487     }
4488   }
4489   PetscFunctionReturn(0);
4490 }
4491 
4492 #undef __FUNCT__
4493 #define __FUNCT__ "DMLocalizeAddCoordinate_Internal"
4494 /*
4495   DMLocalizeAddCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer.
4496 
4497   Input Parameters:
4498 + dm     - The DM
4499 . dim    - The spatial dimension
4500 . anchor - The anchor point, the input point can be no more than maxCell away from it
4501 . in     - The input coordinate delta (dim numbers)
4502 - out    - The input coordinate point (dim numbers)
4503 
4504   Output Parameter:
4505 . out    - The localized coordinate in + out
4506 
4507   Level: developer
4508 
4509   Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell
4510 
4511 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate()
4512 */
4513 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
4514 {
4515   PetscInt d;
4516 
4517   PetscFunctionBegin;
4518   if (!dm->maxCell) {
4519     for (d = 0; d < dim; ++d) out[d] += in[d];
4520   } else {
4521     for (d = 0; d < dim; ++d) {
4522       if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) {
4523         out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
4524       } else {
4525         out[d] += in[d];
4526       }
4527     }
4528   }
4529   PetscFunctionReturn(0);
4530 }
4531 
4532 PETSC_EXTERN PetscErrorCode DMPlexGetDepthStratum(DM, PetscInt, PetscInt *, PetscInt *);
4533 PETSC_EXTERN PetscErrorCode DMPlexGetHeightStratum(DM, PetscInt, PetscInt *, PetscInt *);
4534 PETSC_EXTERN PetscErrorCode DMPlexVecGetClosure(DM, PetscSection, Vec, PetscInt, PetscInt *, PetscScalar *[]);
4535 PETSC_EXTERN PetscErrorCode DMPlexVecRestoreClosure(DM, PetscSection, Vec, PetscInt, PetscInt *, PetscScalar *[]);
4536 
4537 #undef __FUNCT__
4538 #define __FUNCT__ "DMLocalizeCoordinates"
4539 /*@
4540   DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for each cell
4541 
4542   Input Parameter:
4543 . dm - The DM
4544 
4545   Level: developer
4546 
4547 .seealso: DMLocalizeCoordinate(), DMLocalizeAddCoordinate()
4548 @*/
4549 PetscErrorCode DMLocalizeCoordinates(DM dm)
4550 {
4551   DM             cdm;
4552   PetscSection   coordSection, cSection;
4553   Vec            coordinates,  cVec;
4554   PetscScalar   *coords, *coords2, *anchor;
4555   PetscInt       Nc, cStart, cEnd, c, vStart, vEnd, v, dof, d, off, off2, bs, coordSize;
4556   PetscErrorCode ierr;
4557 
4558   PetscFunctionBegin;
4559   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4560   if (!dm->maxCell) PetscFunctionReturn(0);
4561   /* We need some generic way of refering to cells/vertices */
4562   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
4563   {
4564     PetscBool isplex;
4565 
4566     ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr);
4567     if (isplex) {
4568       ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr);
4569       ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr);
4570     } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM");
4571   }
4572   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
4573   ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
4574   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr);
4575   ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr);
4576   ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr);
4577   ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr);
4578   ierr = PetscSectionSetChart(cSection, cStart, vEnd);CHKERRQ(ierr);
4579   for (v = vStart; v < vEnd; ++v) {
4580     ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr);
4581     ierr = PetscSectionSetDof(cSection,     v,  dof);CHKERRQ(ierr);
4582     ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr);
4583   }
4584   for (c = cStart; c < cEnd; ++c) {
4585     ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, NULL);CHKERRQ(ierr);
4586     ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr);
4587     ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr);
4588   }
4589   ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr);
4590   ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr);
4591   ierr = VecCreate(PetscObjectComm((PetscObject) dm), &cVec);CHKERRQ(ierr);
4592   ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr);
4593   ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr);
4594   ierr = VecSetBlockSize(cVec,         bs);CHKERRQ(ierr);
4595   ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr);
4596   ierr = VecSetType(cVec,VECSTANDARD);CHKERRQ(ierr);
4597   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
4598   ierr = VecGetArray(cVec,        &coords2);CHKERRQ(ierr);
4599   for (v = vStart; v < vEnd; ++v) {
4600     ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr);
4601     ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
4602     ierr = PetscSectionGetOffset(cSection,     v, &off2);CHKERRQ(ierr);
4603     for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d];
4604   }
4605   ierr = DMGetWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr);
4606   for (c = cStart; c < cEnd; ++c) {
4607     PetscScalar *cellCoords = NULL;
4608     PetscInt     b;
4609 
4610     ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr);
4611     ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr);
4612     for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b];
4613     for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);}
4614     ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr);
4615   }
4616   ierr = DMRestoreWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr);
4617   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
4618   ierr = VecRestoreArray(cVec,        &coords2);CHKERRQ(ierr);
4619   ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr);
4620   ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr);
4621   ierr = VecDestroy(&cVec);CHKERRQ(ierr);
4622   ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr);
4623   PetscFunctionReturn(0);
4624 }
4625 
4626 #undef __FUNCT__
4627 #define __FUNCT__ "DMLocatePoints"
4628 /*@
4629   DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells
4630 
4631   Not collective
4632 
4633   Input Parameters:
4634 + dm - The DM
4635 - v - The Vec of points
4636 
4637   Output Parameter:
4638 . cells - The local cell numbers for cells which contain the points
4639 
4640   Level: developer
4641 
4642 .keywords: point location, mesh
4643 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4644 @*/
4645 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells)
4646 {
4647   PetscErrorCode ierr;
4648 
4649   PetscFunctionBegin;
4650   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4651   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4652   PetscValidPointer(cells,3);
4653   ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr);
4654   if (dm->ops->locatepoints) {
4655     ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr);
4656   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM");
4657   ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr);
4658   PetscFunctionReturn(0);
4659 }
4660 
4661 #undef __FUNCT__
4662 #define __FUNCT__ "DMGetOutputDM"
4663 /*@
4664   DMGetOutputDM - Retrieve the DM associated with the layout for output
4665 
4666   Input Parameter:
4667 . dm - The original DM
4668 
4669   Output Parameter:
4670 . odm - The DM which provides the layout for output
4671 
4672   Level: intermediate
4673 
4674 .seealso: VecView(), DMGetDefaultGlobalSection()
4675 @*/
4676 PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
4677 {
4678   PetscSection   section;
4679   PetscBool      hasConstraints;
4680   PetscErrorCode ierr;
4681 
4682   PetscFunctionBegin;
4683   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4684   PetscValidPointer(odm,2);
4685   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
4686   ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr);
4687   if (!hasConstraints) {
4688     *odm = dm;
4689     PetscFunctionReturn(0);
4690   }
4691   if (!dm->dmBC) {
4692     PetscSection newSection, gsection;
4693     PetscSF      sf;
4694 
4695     ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr);
4696     ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr);
4697     ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr);
4698     ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr);
4699     ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr);
4700     ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr);
4701     ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr);
4702     ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr);
4703   }
4704   *odm = dm->dmBC;
4705   PetscFunctionReturn(0);
4706 }
4707 
4708 #undef __FUNCT__
4709 #define __FUNCT__ "DMGetOutputSequenceNumber"
4710 /*@
4711   DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
4712 
4713   Input Parameter:
4714 . dm - The original DM
4715 
4716   Output Parameters:
4717 + num - The output sequence number
4718 - val - The output sequence value
4719 
4720   Level: intermediate
4721 
4722   Note: This is intended for output that should appear in sequence, for instance
4723   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
4724 
4725 .seealso: VecView()
4726 @*/
4727 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
4728 {
4729   PetscFunctionBegin;
4730   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4731   if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;}
4732   if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;}
4733   PetscFunctionReturn(0);
4734 }
4735 
4736 #undef __FUNCT__
4737 #define __FUNCT__ "DMSetOutputSequenceNumber"
4738 /*@
4739   DMSetOutputSequenceNumber - Set the sequence number/value for output
4740 
4741   Input Parameters:
4742 + dm - The original DM
4743 . num - The output sequence number
4744 - val - The output sequence value
4745 
4746   Level: intermediate
4747 
4748   Note: This is intended for output that should appear in sequence, for instance
4749   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
4750 
4751 .seealso: VecView()
4752 @*/
4753 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
4754 {
4755   PetscFunctionBegin;
4756   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4757   dm->outputSequenceNum = num;
4758   dm->outputSequenceVal = val;
4759   PetscFunctionReturn(0);
4760 }
4761 
4762 #undef __FUNCT__
4763 #define __FUNCT__ "DMOutputSequenceLoad"
4764 /*@C
4765   DMOutputSequenceLoad - Retrieve the sequence value from a Viewer
4766 
4767   Input Parameters:
4768 + dm   - The original DM
4769 . name - The sequence name
4770 - num  - The output sequence number
4771 
4772   Output Parameter:
4773 . val  - The output sequence value
4774 
4775   Level: intermediate
4776 
4777   Note: This is intended for output that should appear in sequence, for instance
4778   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
4779 
4780 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView()
4781 @*/
4782 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
4783 {
4784   PetscBool      ishdf5;
4785   PetscErrorCode ierr;
4786 
4787   PetscFunctionBegin;
4788   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4789   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4790   PetscValidPointer(val,4);
4791   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
4792   if (ishdf5) {
4793 #if defined(PETSC_HAVE_HDF5)
4794     PetscScalar value;
4795 
4796     ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr);
4797     *val = PetscRealPart(value);
4798 #endif
4799   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
4800   PetscFunctionReturn(0);
4801 }
4802 
4803 #undef __FUNCT__
4804 #define __FUNCT__ "DMGetUseNatural"
4805 /*@
4806   DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution
4807 
4808   Not collective
4809 
4810   Input Parameter:
4811 . dm - The DM
4812 
4813   Output Parameter:
4814 . useNatural - The flag to build the mapping to a natural order during distribution
4815 
4816   Level: beginner
4817 
4818 .seealso: DMSetUseNatural(), DMCreate()
4819 @*/
4820 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
4821 {
4822   PetscFunctionBegin;
4823   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4824   PetscValidPointer(useNatural, 2);
4825   *useNatural = dm->useNatural;
4826   PetscFunctionReturn(0);
4827 }
4828 
4829 #undef __FUNCT__
4830 #define __FUNCT__ "DMSetUseNatural"
4831 /*@
4832   DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution
4833 
4834   Collective on dm
4835 
4836   Input Parameters:
4837 + dm - The DM
4838 - useNatural - The flag to build the mapping to a natural order during distribution
4839 
4840   Level: beginner
4841 
4842 .seealso: DMGetUseNatural(), DMCreate()
4843 @*/
4844 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
4845 {
4846   PetscFunctionBegin;
4847   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4848   PetscValidLogicalCollectiveInt(dm, useNatural, 2);
4849   dm->useNatural = useNatural;
4850   PetscFunctionReturn(0);
4851 }
4852 
4853 #undef __FUNCT__
4854 #define __FUNCT__
4855 
4856 #undef __FUNCT__
4857 #define __FUNCT__ "DMCreateLabel"
4858 /*@C
4859   DMCreateLabel - Create a label of the given name if it does not already exist
4860 
4861   Not Collective
4862 
4863   Input Parameters:
4864 + dm   - The DM object
4865 - name - The label name
4866 
4867   Level: intermediate
4868 
4869 .keywords: mesh
4870 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
4871 @*/
4872 PetscErrorCode DMCreateLabel(DM dm, const char name[])
4873 {
4874   DMLabelLink    next  = dm->labels->next;
4875   PetscBool      flg   = PETSC_FALSE;
4876   PetscErrorCode ierr;
4877 
4878   PetscFunctionBegin;
4879   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4880   PetscValidCharPointer(name, 2);
4881   while (next) {
4882     ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr);
4883     if (flg) break;
4884     next = next->next;
4885   }
4886   if (!flg) {
4887     DMLabelLink tmpLabel;
4888 
4889     ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr);
4890     ierr = DMLabelCreate(name, &tmpLabel->label);CHKERRQ(ierr);
4891     tmpLabel->output = PETSC_TRUE;
4892     tmpLabel->next   = dm->labels->next;
4893     dm->labels->next = tmpLabel;
4894   }
4895   PetscFunctionReturn(0);
4896 }
4897 
4898 #undef __FUNCT__
4899 #define __FUNCT__ "DMGetLabelValue"
4900 /*@C
4901   DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default
4902 
4903   Not Collective
4904 
4905   Input Parameters:
4906 + dm   - The DM object
4907 . name - The label name
4908 - point - The mesh point
4909 
4910   Output Parameter:
4911 . value - The label value for this point, or -1 if the point is not in the label
4912 
4913   Level: beginner
4914 
4915 .keywords: mesh
4916 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS()
4917 @*/
4918 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
4919 {
4920   DMLabel        label;
4921   PetscErrorCode ierr;
4922 
4923   PetscFunctionBegin;
4924   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4925   PetscValidCharPointer(name, 2);
4926   ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
4927   if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);CHKERRQ(ierr);
4928   ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr);
4929   PetscFunctionReturn(0);
4930 }
4931 
4932 #undef __FUNCT__
4933 #define __FUNCT__ "DMSetLabelValue"
4934 /*@C
4935   DMSetLabelValue - Add a point to a Sieve Label with given value
4936 
4937   Not Collective
4938 
4939   Input Parameters:
4940 + dm   - The DM object
4941 . name - The label name
4942 . point - The mesh point
4943 - value - The label value for this point
4944 
4945   Output Parameter:
4946 
4947   Level: beginner
4948 
4949 .keywords: mesh
4950 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue()
4951 @*/
4952 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
4953 {
4954   DMLabel        label;
4955   PetscErrorCode ierr;
4956 
4957   PetscFunctionBegin;
4958   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4959   PetscValidCharPointer(name, 2);
4960   ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
4961   if (!label) {
4962     ierr = DMCreateLabel(dm, name);CHKERRQ(ierr);
4963     ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
4964   }
4965   ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr);
4966   PetscFunctionReturn(0);
4967 }
4968 
4969 #undef __FUNCT__
4970 #define __FUNCT__ "DMClearLabelValue"
4971 /*@C
4972   DMClearLabelValue - Remove a point from a Sieve Label with given value
4973 
4974   Not Collective
4975 
4976   Input Parameters:
4977 + dm   - The DM object
4978 . name - The label name
4979 . point - The mesh point
4980 - value - The label value for this point
4981 
4982   Output Parameter:
4983 
4984   Level: beginner
4985 
4986 .keywords: mesh
4987 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS()
4988 @*/
4989 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
4990 {
4991   DMLabel        label;
4992   PetscErrorCode ierr;
4993 
4994   PetscFunctionBegin;
4995   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4996   PetscValidCharPointer(name, 2);
4997   ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
4998   if (!label) PetscFunctionReturn(0);
4999   ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr);
5000   PetscFunctionReturn(0);
5001 }
5002 
5003 #undef __FUNCT__
5004 #define __FUNCT__ "DMGetLabelSize"
5005 /*@C
5006   DMGetLabelSize - Get the number of different integer ids in a Label
5007 
5008   Not Collective
5009 
5010   Input Parameters:
5011 + dm   - The DM object
5012 - name - The label name
5013 
5014   Output Parameter:
5015 . size - The number of different integer ids, or 0 if the label does not exist
5016 
5017   Level: beginner
5018 
5019 .keywords: mesh
5020 .seealso: DMLabeGetNumValues(), DMSetLabelValue()
5021 @*/
5022 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size)
5023 {
5024   DMLabel        label;
5025   PetscErrorCode ierr;
5026 
5027   PetscFunctionBegin;
5028   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5029   PetscValidCharPointer(name, 2);
5030   PetscValidPointer(size, 3);
5031   ierr  = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
5032   *size = 0;
5033   if (!label) PetscFunctionReturn(0);
5034   ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr);
5035   PetscFunctionReturn(0);
5036 }
5037 
5038 #undef __FUNCT__
5039 #define __FUNCT__ "DMGetLabelIdIS"
5040 /*@C
5041   DMGetLabelIdIS - Get the integer ids in a label
5042 
5043   Not Collective
5044 
5045   Input Parameters:
5046 + mesh - The DM object
5047 - name - The label name
5048 
5049   Output Parameter:
5050 . ids - The integer ids, or NULL if the label does not exist
5051 
5052   Level: beginner
5053 
5054 .keywords: mesh
5055 .seealso: DMLabelGetValueIS(), DMGetLabelSize()
5056 @*/
5057 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids)
5058 {
5059   DMLabel        label;
5060   PetscErrorCode ierr;
5061 
5062   PetscFunctionBegin;
5063   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5064   PetscValidCharPointer(name, 2);
5065   PetscValidPointer(ids, 3);
5066   ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
5067   *ids = NULL;
5068   if (!label) PetscFunctionReturn(0);
5069   ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr);
5070   PetscFunctionReturn(0);
5071 }
5072 
5073 #undef __FUNCT__
5074 #define __FUNCT__ "DMGetStratumSize"
5075 /*@C
5076   DMGetStratumSize - Get the number of points in a label stratum
5077 
5078   Not Collective
5079 
5080   Input Parameters:
5081 + dm - The DM object
5082 . name - The label name
5083 - value - The stratum value
5084 
5085   Output Parameter:
5086 . size - The stratum size
5087 
5088   Level: beginner
5089 
5090 .keywords: mesh
5091 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds()
5092 @*/
5093 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
5094 {
5095   DMLabel        label;
5096   PetscErrorCode ierr;
5097 
5098   PetscFunctionBegin;
5099   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5100   PetscValidCharPointer(name, 2);
5101   PetscValidPointer(size, 4);
5102   ierr  = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
5103   *size = 0;
5104   if (!label) PetscFunctionReturn(0);
5105   ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr);
5106   PetscFunctionReturn(0);
5107 }
5108 
5109 #undef __FUNCT__
5110 #define __FUNCT__ "DMGetStratumIS"
5111 /*@C
5112   DMGetStratumIS - Get the points in a label stratum
5113 
5114   Not Collective
5115 
5116   Input Parameters:
5117 + dm - The DM object
5118 . name - The label name
5119 - value - The stratum value
5120 
5121   Output Parameter:
5122 . points - The stratum points, or NULL if the label does not exist or does not have that value
5123 
5124   Level: beginner
5125 
5126 .keywords: mesh
5127 .seealso: DMLabelGetStratumIS(), DMGetStratumSize()
5128 @*/
5129 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points)
5130 {
5131   DMLabel        label;
5132   PetscErrorCode ierr;
5133 
5134   PetscFunctionBegin;
5135   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5136   PetscValidCharPointer(name, 2);
5137   PetscValidPointer(points, 4);
5138   ierr    = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
5139   *points = NULL;
5140   if (!label) PetscFunctionReturn(0);
5141   ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr);
5142   PetscFunctionReturn(0);
5143 }
5144 
5145 #undef __FUNCT__
5146 #define __FUNCT__ "DMClearLabelStratum"
5147 /*@C
5148   DMClearLabelStratum - Remove all points from a stratum from a Sieve Label
5149 
5150   Not Collective
5151 
5152   Input Parameters:
5153 + dm   - The DM object
5154 . name - The label name
5155 - value - The label value for this point
5156 
5157   Output Parameter:
5158 
5159   Level: beginner
5160 
5161 .keywords: mesh
5162 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue()
5163 @*/
5164 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value)
5165 {
5166   DMLabel        label;
5167   PetscErrorCode ierr;
5168 
5169   PetscFunctionBegin;
5170   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5171   PetscValidCharPointer(name, 2);
5172   ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
5173   if (!label) PetscFunctionReturn(0);
5174   ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr);
5175   PetscFunctionReturn(0);
5176 }
5177 
5178 #undef __FUNCT__
5179 #define __FUNCT__ "DMGetNumLabels"
5180 /*@
5181   DMGetNumLabels - Return the number of labels defined by the mesh
5182 
5183   Not Collective
5184 
5185   Input Parameter:
5186 . dm   - The DM object
5187 
5188   Output Parameter:
5189 . numLabels - the number of Labels
5190 
5191   Level: intermediate
5192 
5193 .keywords: mesh
5194 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5195 @*/
5196 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels)
5197 {
5198   DMLabelLink next = dm->labels->next;
5199   PetscInt  n    = 0;
5200 
5201   PetscFunctionBegin;
5202   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5203   PetscValidPointer(numLabels, 2);
5204   while (next) {++n; next = next->next;}
5205   *numLabels = n;
5206   PetscFunctionReturn(0);
5207 }
5208 
5209 #undef __FUNCT__
5210 #define __FUNCT__ "DMGetLabelName"
5211 /*@C
5212   DMGetLabelName - Return the name of nth label
5213 
5214   Not Collective
5215 
5216   Input Parameters:
5217 + dm - The DM object
5218 - n  - the label number
5219 
5220   Output Parameter:
5221 . name - the label name
5222 
5223   Level: intermediate
5224 
5225 .keywords: mesh
5226 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5227 @*/
5228 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name)
5229 {
5230   DMLabelLink next = dm->labels->next;
5231   PetscInt  l    = 0;
5232 
5233   PetscFunctionBegin;
5234   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5235   PetscValidPointer(name, 3);
5236   while (next) {
5237     if (l == n) {
5238       *name = next->label->name;
5239       PetscFunctionReturn(0);
5240     }
5241     ++l;
5242     next = next->next;
5243   }
5244   SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n);
5245 }
5246 
5247 #undef __FUNCT__
5248 #define __FUNCT__ "DMHasLabel"
5249 /*@C
5250   DMHasLabel - Determine whether the mesh has a label of a given name
5251 
5252   Not Collective
5253 
5254   Input Parameters:
5255 + dm   - The DM object
5256 - name - The label name
5257 
5258   Output Parameter:
5259 . hasLabel - PETSC_TRUE if the label is present
5260 
5261   Level: intermediate
5262 
5263 .keywords: mesh
5264 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5265 @*/
5266 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel)
5267 {
5268   DMLabelLink    next = dm->labels->next;
5269   PetscErrorCode ierr;
5270 
5271   PetscFunctionBegin;
5272   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5273   PetscValidCharPointer(name, 2);
5274   PetscValidPointer(hasLabel, 3);
5275   *hasLabel = PETSC_FALSE;
5276   while (next) {
5277     ierr = PetscStrcmp(name, next->label->name, hasLabel);CHKERRQ(ierr);
5278     if (*hasLabel) break;
5279     next = next->next;
5280   }
5281   PetscFunctionReturn(0);
5282 }
5283 
5284 #undef __FUNCT__
5285 #define __FUNCT__ "DMGetLabel"
5286 /*@C
5287   DMGetLabel - Return the label of a given name, or NULL
5288 
5289   Not Collective
5290 
5291   Input Parameters:
5292 + dm   - The DM object
5293 - name - The label name
5294 
5295   Output Parameter:
5296 . label - The DMLabel, or NULL if the label is absent
5297 
5298   Level: intermediate
5299 
5300 .keywords: mesh
5301 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5302 @*/
5303 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label)
5304 {
5305   DMLabelLink    next = dm->labels->next;
5306   PetscBool      hasLabel;
5307   PetscErrorCode ierr;
5308 
5309   PetscFunctionBegin;
5310   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5311   PetscValidCharPointer(name, 2);
5312   PetscValidPointer(label, 3);
5313   *label = NULL;
5314   while (next) {
5315     ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr);
5316     if (hasLabel) {
5317       *label = next->label;
5318       break;
5319     }
5320     next = next->next;
5321   }
5322   PetscFunctionReturn(0);
5323 }
5324 
5325 #undef __FUNCT__
5326 #define __FUNCT__ "DMGetLabelByNum"
5327 /*@C
5328   DMGetLabelByNum - Return the nth label
5329 
5330   Not Collective
5331 
5332   Input Parameters:
5333 + dm - The DM object
5334 - n  - the label number
5335 
5336   Output Parameter:
5337 . label - the label
5338 
5339   Level: intermediate
5340 
5341 .keywords: mesh
5342 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5343 @*/
5344 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label)
5345 {
5346   DMLabelLink next = dm->labels->next;
5347   PetscInt    l    = 0;
5348 
5349   PetscFunctionBegin;
5350   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5351   PetscValidPointer(label, 3);
5352   while (next) {
5353     if (l == n) {
5354       *label = next->label;
5355       PetscFunctionReturn(0);
5356     }
5357     ++l;
5358     next = next->next;
5359   }
5360   SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n);
5361 }
5362 
5363 #undef __FUNCT__
5364 #define __FUNCT__ "DMAddLabel"
5365 /*@C
5366   DMAddLabel - Add the label to this mesh
5367 
5368   Not Collective
5369 
5370   Input Parameters:
5371 + dm   - The DM object
5372 - label - The DMLabel
5373 
5374   Level: developer
5375 
5376 .keywords: mesh
5377 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5378 @*/
5379 PetscErrorCode DMAddLabel(DM dm, DMLabel label)
5380 {
5381   DMLabelLink    tmpLabel;
5382   PetscBool      hasLabel;
5383   PetscErrorCode ierr;
5384 
5385   PetscFunctionBegin;
5386   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5387   ierr = DMHasLabel(dm, label->name, &hasLabel);CHKERRQ(ierr);
5388   if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name);
5389   ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr);
5390   tmpLabel->label  = label;
5391   tmpLabel->output = PETSC_TRUE;
5392   tmpLabel->next   = dm->labels->next;
5393   dm->labels->next = tmpLabel;
5394   PetscFunctionReturn(0);
5395 }
5396 
5397 #undef __FUNCT__
5398 #define __FUNCT__ "DMRemoveLabel"
5399 /*@C
5400   DMRemoveLabel - Remove the label from this mesh
5401 
5402   Not Collective
5403 
5404   Input Parameters:
5405 + dm   - The DM object
5406 - name - The label name
5407 
5408   Output Parameter:
5409 . label - The DMLabel, or NULL if the label is absent
5410 
5411   Level: developer
5412 
5413 .keywords: mesh
5414 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5415 @*/
5416 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label)
5417 {
5418   DMLabelLink    next = dm->labels->next;
5419   DMLabelLink    last = NULL;
5420   PetscBool      hasLabel;
5421   PetscErrorCode ierr;
5422 
5423   PetscFunctionBegin;
5424   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5425   ierr   = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr);
5426   *label = NULL;
5427   if (!hasLabel) PetscFunctionReturn(0);
5428   while (next) {
5429     ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr);
5430     if (hasLabel) {
5431       if (last) last->next       = next->next;
5432       else      dm->labels->next = next->next;
5433       next->next = NULL;
5434       *label     = next->label;
5435       ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr);
5436       if (hasLabel) {
5437         dm->depthLabel = NULL;
5438       }
5439       ierr = PetscFree(next);CHKERRQ(ierr);
5440       break;
5441     }
5442     last = next;
5443     next = next->next;
5444   }
5445   PetscFunctionReturn(0);
5446 }
5447 
5448 #undef __FUNCT__
5449 #define __FUNCT__ "DMGetLabelOutput"
5450 /*@C
5451   DMGetLabelOutput - Get the output flag for a given label
5452 
5453   Not Collective
5454 
5455   Input Parameters:
5456 + dm   - The DM object
5457 - name - The label name
5458 
5459   Output Parameter:
5460 . output - The flag for output
5461 
5462   Level: developer
5463 
5464 .keywords: mesh
5465 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5466 @*/
5467 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output)
5468 {
5469   DMLabelLink    next = dm->labels->next;
5470   PetscErrorCode ierr;
5471 
5472   PetscFunctionBegin;
5473   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5474   PetscValidPointer(name, 2);
5475   PetscValidPointer(output, 3);
5476   while (next) {
5477     PetscBool flg;
5478 
5479     ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr);
5480     if (flg) {*output = next->output; PetscFunctionReturn(0);}
5481     next = next->next;
5482   }
5483   SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
5484 }
5485 
5486 #undef __FUNCT__
5487 #define __FUNCT__ "DMSetLabelOutput"
5488 /*@C
5489   DMSetLabelOutput - Set the output flag for a given label
5490 
5491   Not Collective
5492 
5493   Input Parameters:
5494 + dm     - The DM object
5495 . name   - The label name
5496 - output - The flag for output
5497 
5498   Level: developer
5499 
5500 .keywords: mesh
5501 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5502 @*/
5503 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output)
5504 {
5505   DMLabelLink    next = dm->labels->next;
5506   PetscErrorCode ierr;
5507 
5508   PetscFunctionBegin;
5509   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5510   PetscValidPointer(name, 2);
5511   while (next) {
5512     PetscBool flg;
5513 
5514     ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr);
5515     if (flg) {next->output = output; PetscFunctionReturn(0);}
5516     next = next->next;
5517   }
5518   SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
5519 }
5520 
5521 
5522 #undef __FUNCT__
5523 #define __FUNCT__ "DMCopyLabels"
5524 /*@
5525   DMCopyLabels - Copy labels from one mesh to another with a superset of the points
5526 
5527   Collective on DM
5528 
5529   Input Parameter:
5530 . dmA - The DM object with initial labels
5531 
5532   Output Parameter:
5533 . dmB - The DM object with copied labels
5534 
5535   Level: intermediate
5536 
5537   Note: This is typically used when interpolating or otherwise adding to a mesh
5538 
5539 .keywords: mesh
5540 .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection()
5541 @*/
5542 PetscErrorCode DMCopyLabels(DM dmA, DM dmB)
5543 {
5544   PetscInt       numLabels, l;
5545   PetscErrorCode ierr;
5546 
5547   PetscFunctionBegin;
5548   if (dmA == dmB) PetscFunctionReturn(0);
5549   ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr);
5550   for (l = 0; l < numLabels; ++l) {
5551     DMLabel     label, labelNew;
5552     const char *name;
5553     PetscBool   flg;
5554 
5555     ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr);
5556     ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr);
5557     if (flg) continue;
5558     ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr);
5559     ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr);
5560     ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr);
5561   }
5562   PetscFunctionReturn(0);
5563 }
5564 
5565 #undef __FUNCT__
5566 #define __FUNCT__ "DMGetCoarseDM"
5567 /*@
5568   DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement
5569 
5570   Input Parameter:
5571 . dm - The DM object
5572 
5573   Output Parameter:
5574 . cdm - The coarse DM
5575 
5576   Level: intermediate
5577 
5578 .seealso: DMSetCoarseDM()
5579 @*/
5580 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm)
5581 {
5582   PetscFunctionBegin;
5583   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5584   PetscValidPointer(cdm, 2);
5585   *cdm = dm->coarseMesh;
5586   PetscFunctionReturn(0);
5587 }
5588 
5589 #undef __FUNCT__
5590 #define __FUNCT__ "DMSetCoarseDM"
5591 /*@
5592   DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement
5593 
5594   Input Parameters:
5595 + dm - The DM object
5596 - cdm - The coarse DM
5597 
5598   Level: intermediate
5599 
5600 .seealso: DMGetCoarseDM()
5601 @*/
5602 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm)
5603 {
5604   PetscErrorCode ierr;
5605 
5606   PetscFunctionBegin;
5607   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5608   if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2);
5609   ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr);
5610   ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr);
5611   dm->coarseMesh = cdm;
5612   PetscFunctionReturn(0);
5613 }
5614 
5615 #undef __FUNCT__
5616 #define __FUNCT__ "DMGetFineDM"
5617 /*@
5618   DMGetFineDM - Get the fine mesh from which this was obtained by refinement
5619 
5620   Input Parameter:
5621 . dm - The DM object
5622 
5623   Output Parameter:
5624 . fdm - The fine DM
5625 
5626   Level: intermediate
5627 
5628 .seealso: DMSetFineDM()
5629 @*/
5630 PetscErrorCode DMGetFineDM(DM dm, DM *fdm)
5631 {
5632   PetscFunctionBegin;
5633   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5634   PetscValidPointer(fdm, 2);
5635   *fdm = dm->fineMesh;
5636   PetscFunctionReturn(0);
5637 }
5638 
5639 #undef __FUNCT__
5640 #define __FUNCT__ "DMSetFineDM"
5641 /*@
5642   DMSetFineDM - Set the fine mesh from which this was obtained by refinement
5643 
5644   Input Parameters:
5645 + dm - The DM object
5646 - fdm - The fine DM
5647 
5648   Level: intermediate
5649 
5650 .seealso: DMGetFineDM()
5651 @*/
5652 PetscErrorCode DMSetFineDM(DM dm, DM fdm)
5653 {
5654   PetscErrorCode ierr;
5655 
5656   PetscFunctionBegin;
5657   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5658   if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2);
5659   ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr);
5660   ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr);
5661   dm->fineMesh = fdm;
5662   PetscFunctionReturn(0);
5663 }
5664 
5665 /*=== DMBoundary code ===*/
5666 
5667 #undef __FUNCT__
5668 #define __FUNCT__ "DMBoundaryDuplicate"
5669 PetscErrorCode DMBoundaryDuplicate(DMBoundaryLinkList bd, DMBoundaryLinkList *boundary)
5670 {
5671   DMBoundary     b = bd->next, b2, bold = NULL;
5672   PetscErrorCode ierr;
5673 
5674   PetscFunctionBegin;
5675   ierr = PetscNew(boundary);CHKERRQ(ierr);
5676   (*boundary)->refct = 1;
5677   (*boundary)->next = NULL;
5678   for (; b; b = b->next, bold = b2) {
5679     ierr = PetscNew(&b2);CHKERRQ(ierr);
5680     ierr = PetscStrallocpy(b->name, (char **) &b2->name);CHKERRQ(ierr);
5681     ierr = PetscStrallocpy(b->labelname, (char **) &b2->labelname);CHKERRQ(ierr);
5682     ierr = PetscMalloc1(b->numids, &b2->ids);CHKERRQ(ierr);
5683     ierr = PetscMemcpy(b2->ids, b->ids, b->numids*sizeof(PetscInt));CHKERRQ(ierr);
5684     ierr = PetscMalloc1(b->numcomps, &b2->comps);CHKERRQ(ierr);
5685     ierr = PetscMemcpy(b2->comps, b->comps, b->numcomps*sizeof(PetscInt));CHKERRQ(ierr);
5686     b2->label     = NULL;
5687     b2->essential = b->essential;
5688     b2->field     = b->field;
5689     b2->numcomps  = b->numcomps;
5690     b2->func      = b->func;
5691     b2->numids    = b->numids;
5692     b2->ctx       = b->ctx;
5693     b2->next      = NULL;
5694     if (!(*boundary)->next) (*boundary)->next   = b2;
5695     if (bold)        bold->next = b2;
5696   }
5697   PetscFunctionReturn(0);
5698 }
5699 
5700 #undef __FUNCT__
5701 #define __FUNCT__ "DMBoundaryDestroy"
5702 PetscErrorCode DMBoundaryDestroy(DMBoundaryLinkList *boundary)
5703 {
5704   DMBoundary     b, next;
5705   PetscErrorCode ierr;
5706 
5707   PetscFunctionBegin;
5708   if (!boundary) PetscFunctionReturn(0);
5709   if (--((*boundary)->refct)) {
5710     *boundary = NULL;
5711     PetscFunctionReturn(0);
5712   }
5713   b = (*boundary)->next;
5714   for (; b; b = next) {
5715     next = b->next;
5716     ierr = PetscFree(b->comps);CHKERRQ(ierr);
5717     ierr = PetscFree(b->ids);CHKERRQ(ierr);
5718     ierr = PetscFree(b->name);CHKERRQ(ierr);
5719     ierr = PetscFree(b->labelname);CHKERRQ(ierr);
5720     ierr = PetscFree(b);CHKERRQ(ierr);
5721   }
5722   ierr = PetscFree(*boundary);CHKERRQ(ierr);
5723   PetscFunctionReturn(0);
5724 }
5725 
5726 #undef __FUNCT__
5727 #define __FUNCT__ "DMCopyBoundary"
5728 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew)
5729 {
5730   DMBoundary     b;
5731   PetscErrorCode ierr;
5732 
5733   PetscFunctionBegin;
5734   ierr = DMBoundaryDestroy(&dmNew->boundary);CHKERRQ(ierr);
5735   ierr = DMBoundaryDuplicate(dm->boundary, &dmNew->boundary);CHKERRQ(ierr);
5736   for (b = dmNew->boundary->next; b; b = b->next) {
5737     if (b->labelname) {
5738       ierr = DMGetLabel(dmNew, b->labelname, &b->label);CHKERRQ(ierr);
5739       if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname);
5740     }
5741   }
5742   PetscFunctionReturn(0);
5743 }
5744 
5745 #undef __FUNCT__
5746 #define __FUNCT__ "DMAddBoundary"
5747 /*@C
5748   DMAddBoundary - Add a boundary condition to the model
5749 
5750   Input Parameters:
5751 + dm          - The mesh object
5752 . isEssential - Flag for an essential (Dirichlet) condition, as opposed to a natural (Neumann) condition
5753 . name        - The BC name
5754 . labelname   - The label defining constrained points
5755 . field       - The field to constrain
5756 . numcomps    - The number of constrained field components
5757 . comps       - An array of constrained component numbers
5758 . bcFunc      - A pointwise function giving boundary values
5759 . numids      - The number of DMLabel ids for constrained points
5760 . ids         - An array of ids for constrained points
5761 - ctx         - An optional user context for bcFunc
5762 
5763   Options Database Keys:
5764 + -bc_<boundary name> <num> - Overrides the boundary ids
5765 - -bc_<boundary name>_comp <num> - Overrides the boundary components
5766 
5767   Level: developer
5768 
5769 .seealso: DMGetBoundary()
5770 @*/
5771 PetscErrorCode DMAddBoundary(DM dm, PetscBool isEssential, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(), PetscInt numids, const PetscInt *ids, void *ctx)
5772 {
5773   DMBoundary     b;
5774   PetscErrorCode ierr;
5775 
5776   PetscFunctionBegin;
5777   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5778   ierr = PetscNew(&b);CHKERRQ(ierr);
5779   ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr);
5780   ierr = PetscStrallocpy(labelname, (char **) &b->labelname);CHKERRQ(ierr);
5781   ierr = PetscMalloc1(numcomps, &b->comps);CHKERRQ(ierr);
5782   if (numcomps) {ierr = PetscMemcpy(b->comps, comps, numcomps*sizeof(PetscInt));CHKERRQ(ierr);}
5783   ierr = PetscMalloc1(numids, &b->ids);CHKERRQ(ierr);
5784   if (numids) {ierr = PetscMemcpy(b->ids, ids, numids*sizeof(PetscInt));CHKERRQ(ierr);}
5785   if (b->labelname) {
5786     ierr = DMGetLabel(dm, b->labelname, &b->label);CHKERRQ(ierr);
5787     if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname);
5788   }
5789   b->essential       = isEssential;
5790   b->field           = field;
5791   b->numcomps        = numcomps;
5792   b->func            = bcFunc;
5793   b->numids          = numids;
5794   b->ctx             = ctx;
5795   b->next            = dm->boundary->next;
5796   dm->boundary->next = b;
5797   PetscFunctionReturn(0);
5798 }
5799 
5800 #undef __FUNCT__
5801 #define __FUNCT__ "DMGetNumBoundary"
5802 /*@
5803   DMGetNumBoundary - Get the number of registered BC
5804 
5805   Input Parameters:
5806 . dm - The mesh object
5807 
5808   Output Parameters:
5809 . numBd - The number of BC
5810 
5811   Level: intermediate
5812 
5813 .seealso: DMAddBoundary(), DMGetBoundary()
5814 @*/
5815 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd)
5816 {
5817   DMBoundary b = dm->boundary->next;
5818 
5819   PetscFunctionBegin;
5820   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5821   PetscValidPointer(numBd, 2);
5822   *numBd = 0;
5823   while (b) {++(*numBd); b = b->next;}
5824   PetscFunctionReturn(0);
5825 }
5826 
5827 #undef __FUNCT__
5828 #define __FUNCT__ "DMGetBoundary"
5829 /*@C
5830   DMGetBoundary - Add a boundary condition to the model
5831 
5832   Input Parameters:
5833 + dm          - The mesh object
5834 - bd          - The BC number
5835 
5836   Output Parameters:
5837 + isEssential - Flag for an essential (Dirichlet) condition, as opposed to a natural (Neumann) condition
5838 . name        - The BC name
5839 . labelname   - The label defining constrained points
5840 . field       - The field to constrain
5841 . numcomps    - The number of constrained field components
5842 . comps       - An array of constrained component numbers
5843 . bcFunc      - A pointwise function giving boundary values
5844 . numids      - The number of DMLabel ids for constrained points
5845 . ids         - An array of ids for constrained points
5846 - ctx         - An optional user context for bcFunc
5847 
5848   Options Database Keys:
5849 + -bc_<boundary name> <num> - Overrides the boundary ids
5850 - -bc_<boundary name>_comp <num> - Overrides the boundary components
5851 
5852   Level: developer
5853 
5854 .seealso: DMAddBoundary()
5855 @*/
5856 PetscErrorCode DMGetBoundary(DM dm, PetscInt bd, PetscBool *isEssential, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(), PetscInt *numids, const PetscInt **ids, void **ctx)
5857 {
5858   DMBoundary b    = dm->boundary->next;
5859   PetscInt   n    = 0;
5860 
5861   PetscFunctionBegin;
5862   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5863   while (b) {
5864     if (n == bd) break;
5865     b = b->next;
5866     ++n;
5867   }
5868   if (n != bd) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n);
5869   if (isEssential) {
5870     PetscValidPointer(isEssential, 3);
5871     *isEssential = b->essential;
5872   }
5873   if (name) {
5874     PetscValidPointer(name, 4);
5875     *name = b->name;
5876   }
5877   if (labelname) {
5878     PetscValidPointer(labelname, 5);
5879     *labelname = b->labelname;
5880   }
5881   if (field) {
5882     PetscValidPointer(field, 6);
5883     *field = b->field;
5884   }
5885   if (numcomps) {
5886     PetscValidPointer(numcomps, 7);
5887     *numcomps = b->numcomps;
5888   }
5889   if (comps) {
5890     PetscValidPointer(comps, 8);
5891     *comps = b->comps;
5892   }
5893   if (func) {
5894     PetscValidPointer(func, 9);
5895     *func = b->func;
5896   }
5897   if (numids) {
5898     PetscValidPointer(numids, 10);
5899     *numids = b->numids;
5900   }
5901   if (ids) {
5902     PetscValidPointer(ids, 11);
5903     *ids = b->ids;
5904   }
5905   if (ctx) {
5906     PetscValidPointer(ctx, 12);
5907     *ctx = b->ctx;
5908   }
5909   PetscFunctionReturn(0);
5910 }
5911 
5912 #undef __FUNCT__
5913 #define __FUNCT__ "DMIsBoundaryPoint"
5914 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd)
5915 {
5916   DMBoundary     b    = dm->boundary->next;
5917   PetscErrorCode ierr;
5918 
5919   PetscFunctionBegin;
5920   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5921   PetscValidPointer(isBd, 3);
5922   *isBd = PETSC_FALSE;
5923   while (b && !(*isBd)) {
5924     if (b->label) {
5925       PetscInt i;
5926 
5927       for (i = 0; i < b->numids && !(*isBd); ++i) {
5928         ierr = DMLabelStratumHasPoint(b->label, b->ids[i], point, isBd);CHKERRQ(ierr);
5929       }
5930     }
5931     b = b->next;
5932   }
5933   PetscFunctionReturn(0);
5934 }
5935 
5936 #undef __FUNCT__
5937 #define __FUNCT__ "DMProjectFunction"
5938 /*@C
5939   DMProjectFunction - This projects the given function into the function space provided.
5940 
5941   Input Parameters:
5942 + dm      - The DM
5943 . time    - The time
5944 . funcs   - The coordinate functions to evaluate, one per field
5945 . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
5946 - mode    - The insertion mode for values
5947 
5948   Output Parameter:
5949 . X - vector
5950 
5951    Calling sequence of func:
5952 $    func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx);
5953 
5954 +  dim - The spatial dimension
5955 .  x   - The coordinates
5956 .  Nf  - The number of fields
5957 .  u   - The output field values
5958 -  ctx - optional user-defined function context
5959 
5960   Level: developer
5961 
5962 .seealso: DMComputeL2Diff()
5963 @*/
5964 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
5965 {
5966   Vec            localX;
5967   PetscErrorCode ierr;
5968 
5969   PetscFunctionBegin;
5970   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5971   ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
5972   ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr);
5973   ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr);
5974   ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr);
5975   ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
5976   PetscFunctionReturn(0);
5977 }
5978 
5979 #undef __FUNCT__
5980 #define __FUNCT__ "DMProjectFunctionLocal"
5981 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
5982 {
5983   PetscErrorCode ierr;
5984 
5985   PetscFunctionBegin;
5986   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
5987   PetscValidHeaderSpecific(localX,VEC_CLASSID,5);
5988   if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFunctionLocal",((PetscObject)dm)->type_name);
5989   ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr);
5990   PetscFunctionReturn(0);
5991 }
5992 
5993 #undef __FUNCT__
5994 #define __FUNCT__ "DMProjectFieldLocal"
5995 PetscErrorCode DMProjectFieldLocal(DM dm, Vec localU,
5996                                    void (**funcs)(PetscInt, PetscInt, PetscInt,
5997                                                   const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
5998                                                   const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
5999                                                   PetscReal, const PetscReal[], PetscScalar[]),
6000                                    InsertMode mode, Vec localX)
6001 {
6002   PetscErrorCode ierr;
6003 
6004   PetscFunctionBegin;
6005   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6006   PetscValidHeaderSpecific(localU,VEC_CLASSID,2);
6007   PetscValidHeaderSpecific(localX,VEC_CLASSID,5);
6008   if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFieldLocal",((PetscObject)dm)->type_name);
6009   ierr = (dm->ops->projectfieldlocal) (dm, localU, funcs, mode, localX);CHKERRQ(ierr);
6010   PetscFunctionReturn(0);
6011 }
6012 
6013 #undef __FUNCT__
6014 #define __FUNCT__ "DMProjectFunctionLabelLocal"
6015 PetscErrorCode DMProjectFunctionLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
6016 {
6017   PetscErrorCode ierr;
6018 
6019   PetscFunctionBegin;
6020   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6021   PetscValidHeaderSpecific(localX,VEC_CLASSID,5);
6022   if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name);
6023   ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, funcs, ctxs, mode, localX);CHKERRQ(ierr);
6024   PetscFunctionReturn(0);
6025 }
6026 
6027 #undef __FUNCT__
6028 #define __FUNCT__ "DMComputeL2Diff"
6029 /*@C
6030   DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
6031 
6032   Input Parameters:
6033 + dm    - The DM
6034 . time  - The time
6035 . funcs - The functions to evaluate for each field component
6036 . ctxs  - Optional array of contexts to pass to each function, or NULL.
6037 - X     - The coefficient vector u_h
6038 
6039   Output Parameter:
6040 . diff - The diff ||u - u_h||_2
6041 
6042   Level: developer
6043 
6044 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff()
6045 @*/
6046 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
6047 {
6048   PetscErrorCode ierr;
6049 
6050   PetscFunctionBegin;
6051   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6052   PetscValidHeaderSpecific(X,VEC_CLASSID,5);
6053   if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMComputeL2Diff",((PetscObject)dm)->type_name);
6054   ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr);
6055   PetscFunctionReturn(0);
6056 }
6057 
6058 #undef __FUNCT__
6059 #define __FUNCT__ "DMComputeL2GradientDiff"
6060 /*@C
6061   DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.
6062 
6063   Input Parameters:
6064 + dm    - The DM
6065 , time  - The time
6066 . funcs - The gradient functions to evaluate for each field component
6067 . ctxs  - Optional array of contexts to pass to each function, or NULL.
6068 . X     - The coefficient vector u_h
6069 - n     - The vector to project along
6070 
6071   Output Parameter:
6072 . diff - The diff ||(grad u - grad u_h) . n||_2
6073 
6074   Level: developer
6075 
6076 .seealso: DMProjectFunction(), DMComputeL2Diff()
6077 @*/
6078 PetscErrorCode DMComputeL2GradientDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff)
6079 {
6080   PetscErrorCode ierr;
6081 
6082   PetscFunctionBegin;
6083   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6084   PetscValidHeaderSpecific(X,VEC_CLASSID,5);
6085   if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name);
6086   ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr);
6087   PetscFunctionReturn(0);
6088 }
6089 
6090 #undef __FUNCT__
6091 #define __FUNCT__ "DMComputeL2FieldDiff"
6092 /*@C
6093   DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components.
6094 
6095   Input Parameters:
6096 + dm    - The DM
6097 . time  - The time
6098 . funcs - The functions to evaluate for each field component
6099 . ctxs  - Optional array of contexts to pass to each function, or NULL.
6100 - X     - The coefficient vector u_h
6101 
6102   Output Parameter:
6103 . diff - The array of differences, ||u^f - u^f_h||_2
6104 
6105   Level: developer
6106 
6107 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff()
6108 @*/
6109 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
6110 {
6111   PetscErrorCode ierr;
6112 
6113   PetscFunctionBegin;
6114   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6115   PetscValidHeaderSpecific(X,VEC_CLASSID,5);
6116   if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMComputeL2FieldDiff",((PetscObject)dm)->type_name);
6117   ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr);
6118   PetscFunctionReturn(0);
6119 }
6120 
6121