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