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