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