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