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