xref: /petsc/src/dm/interface/dm.c (revision b3b16f483fc003469c74bd65da1026d412d9cc03)
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         dsize;
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,&dsize);CHKERRQ(ierr);
1007   if (dsize*count > link->bytes) {
1008     ierr        = PetscFree(link->mem);CHKERRQ(ierr);
1009     ierr        = PetscMalloc(dsize*count,&link->mem);CHKERRQ(ierr);
1010     link->bytes = dsize*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.
1852            INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one.
1853 
1854     Level: beginner
1855 
1856 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()
1857 
1858 @*/
1859 PetscErrorCode  DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
1860 {
1861   PetscSF                 sf;
1862   PetscSection            s, gs;
1863   DMLocalToGlobalHookLink link;
1864   PetscScalar            *lArray, *gArray;
1865   PetscBool               isInsert;
1866   PetscErrorCode          ierr;
1867 
1868   PetscFunctionBegin;
1869   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1870   for (link=dm->ltoghook; link; link=link->next) {
1871     if (link->beginhook) {
1872       ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr);
1873     }
1874   }
1875   ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr);
1876   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1877   ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
1878   switch (mode) {
1879   case INSERT_VALUES:
1880   case INSERT_ALL_VALUES:
1881     isInsert = PETSC_TRUE; break;
1882   case ADD_VALUES:
1883   case ADD_ALL_VALUES:
1884     isInsert = PETSC_FALSE; break;
1885   default:
1886     SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1887   }
1888   if (sf && !isInsert) {
1889     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1890     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
1891     ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPI_SUM);CHKERRQ(ierr);
1892     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1893     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
1894   } else if (s && isInsert) {
1895     PetscInt gStart, pStart, pEnd, p;
1896 
1897     ierr = DMGetDefaultGlobalSection(dm, &gs);CHKERRQ(ierr);
1898     ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1899     ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr);
1900     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1901     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
1902     for (p = pStart; p < pEnd; ++p) {
1903       PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;
1904 
1905       ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
1906       ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr);
1907       ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
1908       ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr);
1909       ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr);
1910       ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr);
1911       /* Ignore off-process data and points with no global data */
1912       if (!gdof || goff < 0) continue;
1913       if (dof != gdof) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof);
1914       /* If no constraints are enforced in the global vector */
1915       if (!gcdof) {
1916         for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d];
1917       /* If constraints are enforced in the global vector */
1918       } else if (cdof == gcdof) {
1919         const PetscInt *cdofs;
1920         PetscInt        cind = 0;
1921 
1922         ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr);
1923         for (d = 0, e = 0; d < dof; ++d) {
1924           if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;}
1925           gArray[goff-gStart+e++] = lArray[off+d];
1926         }
1927       } else SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof);
1928     }
1929     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1930     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
1931   } else {
1932     ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr);
1933   }
1934   PetscFunctionReturn(0);
1935 }
1936 
1937 #undef __FUNCT__
1938 #define __FUNCT__ "DMLocalToGlobalEnd"
1939 /*@
1940     DMLocalToGlobalEnd - updates global vectors from local vectors
1941 
1942     Neighbor-wise Collective on DM
1943 
1944     Input Parameters:
1945 +   dm - the DM object
1946 .   l - the local vector
1947 .   mode - INSERT_VALUES or ADD_VALUES
1948 -   g - the global vector
1949 
1950 
1951     Level: beginner
1952 
1953 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()
1954 
1955 @*/
1956 PetscErrorCode  DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
1957 {
1958   PetscSF                 sf;
1959   PetscSection            s;
1960   DMLocalToGlobalHookLink link;
1961   PetscBool               isInsert;
1962   PetscErrorCode          ierr;
1963 
1964   PetscFunctionBegin;
1965   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1966   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1967   ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
1968   switch (mode) {
1969   case INSERT_VALUES:
1970   case INSERT_ALL_VALUES:
1971     isInsert = PETSC_TRUE; break;
1972   case ADD_VALUES:
1973   case ADD_ALL_VALUES:
1974     isInsert = PETSC_FALSE; break;
1975   default:
1976     SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1977   }
1978   if (sf && !isInsert) {
1979     PetscScalar *lArray, *gArray;
1980 
1981     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1982     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
1983     ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPI_SUM);CHKERRQ(ierr);
1984     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1985     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
1986   } else if (s && isInsert) {
1987   } else {
1988     ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr);
1989   }
1990   for (link=dm->ltoghook; link; link=link->next) {
1991     if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);}
1992   }
1993   PetscFunctionReturn(0);
1994 }
1995 
1996 #undef __FUNCT__
1997 #define __FUNCT__ "DMLocalToLocalBegin"
1998 /*@
1999    DMLocalToLocalBegin - Maps from a local vector (including ghost points
2000    that contain irrelevant values) to another local vector where the ghost
2001    points in the second are set correctly. Must be followed by DMLocalToLocalEnd().
2002 
2003    Neighbor-wise Collective on DM and Vec
2004 
2005    Input Parameters:
2006 +  dm - the DM object
2007 .  g - the original local vector
2008 -  mode - one of INSERT_VALUES or ADD_VALUES
2009 
2010    Output Parameter:
2011 .  l  - the local vector with correct ghost values
2012 
2013    Level: intermediate
2014 
2015    Notes:
2016    The local vectors used here need not be the same as those
2017    obtained from DMCreateLocalVector(), BUT they
2018    must have the same parallel data layout; they could, for example, be
2019    obtained with VecDuplicate() from the DM originating vectors.
2020 
2021 .keywords: DM, local-to-local, begin
2022 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2023 
2024 @*/
2025 PetscErrorCode  DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2026 {
2027   PetscErrorCode          ierr;
2028 
2029   PetscFunctionBegin;
2030   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2031   ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
2032   PetscFunctionReturn(0);
2033 }
2034 
2035 #undef __FUNCT__
2036 #define __FUNCT__ "DMLocalToLocalEnd"
2037 /*@
2038    DMLocalToLocalEnd - Maps from a local vector (including ghost points
2039    that contain irrelevant values) to another local vector where the ghost
2040    points in the second are set correctly. Must be preceded by DMLocalToLocalBegin().
2041 
2042    Neighbor-wise Collective on DM and Vec
2043 
2044    Input Parameters:
2045 +  da - the DM object
2046 .  g - the original local vector
2047 -  mode - one of INSERT_VALUES or ADD_VALUES
2048 
2049    Output Parameter:
2050 .  l  - the local vector with correct ghost values
2051 
2052    Level: intermediate
2053 
2054    Notes:
2055    The local vectors used here need not be the same as those
2056    obtained from DMCreateLocalVector(), BUT they
2057    must have the same parallel data layout; they could, for example, be
2058    obtained with VecDuplicate() from the DM originating vectors.
2059 
2060 .keywords: DM, local-to-local, end
2061 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2062 
2063 @*/
2064 PetscErrorCode  DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2065 {
2066   PetscErrorCode          ierr;
2067 
2068   PetscFunctionBegin;
2069   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2070   ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
2071   PetscFunctionReturn(0);
2072 }
2073 
2074 
2075 #undef __FUNCT__
2076 #define __FUNCT__ "DMCoarsen"
2077 /*@
2078     DMCoarsen - Coarsens a DM object
2079 
2080     Collective on DM
2081 
2082     Input Parameter:
2083 +   dm - the DM object
2084 -   comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
2085 
2086     Output Parameter:
2087 .   dmc - the coarsened DM
2088 
2089     Level: developer
2090 
2091 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2092 
2093 @*/
2094 PetscErrorCode  DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
2095 {
2096   PetscErrorCode    ierr;
2097   DMCoarsenHookLink link;
2098 
2099   PetscFunctionBegin;
2100   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2101   ierr                      = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr);
2102   (*dmc)->ops->creatematrix = dm->ops->creatematrix;
2103   ierr                      = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr);
2104   (*dmc)->ctx               = dm->ctx;
2105   (*dmc)->levelup           = dm->levelup;
2106   (*dmc)->leveldown         = dm->leveldown + 1;
2107   ierr                      = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr);
2108   for (link=dm->coarsenhook; link; link=link->next) {
2109     if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);}
2110   }
2111   PetscFunctionReturn(0);
2112 }
2113 
2114 #undef __FUNCT__
2115 #define __FUNCT__ "DMCoarsenHookAdd"
2116 /*@C
2117    DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
2118 
2119    Logically Collective
2120 
2121    Input Arguments:
2122 +  fine - nonlinear solver context on which to run a hook when restricting to a coarser level
2123 .  coarsenhook - function to run when setting up a coarser level
2124 .  restricthook - function to run to update data on coarser levels (once per SNESSolve())
2125 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2126 
2127    Calling sequence of coarsenhook:
2128 $    coarsenhook(DM fine,DM coarse,void *ctx);
2129 
2130 +  fine - fine level DM
2131 .  coarse - coarse level DM to restrict problem to
2132 -  ctx - optional user-defined function context
2133 
2134    Calling sequence for restricthook:
2135 $    restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx)
2136 
2137 +  fine - fine level DM
2138 .  mrestrict - matrix restricting a fine-level solution to the coarse grid
2139 .  rscale - scaling vector for restriction
2140 .  inject - matrix restricting by injection
2141 .  coarse - coarse level DM to update
2142 -  ctx - optional user-defined function context
2143 
2144    Level: advanced
2145 
2146    Notes:
2147    This function is only needed if auxiliary data needs to be set up on coarse grids.
2148 
2149    If this function is called multiple times, the hooks will be run in the order they are added.
2150 
2151    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2152    extract the finest level information from its context (instead of from the SNES).
2153 
2154    This function is currently not available from Fortran.
2155 
2156 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2157 @*/
2158 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
2159 {
2160   PetscErrorCode    ierr;
2161   DMCoarsenHookLink link,*p;
2162 
2163   PetscFunctionBegin;
2164   PetscValidHeaderSpecific(fine,DM_CLASSID,1);
2165   for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2166   ierr               = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&link);CHKERRQ(ierr);
2167   link->coarsenhook  = coarsenhook;
2168   link->restricthook = restricthook;
2169   link->ctx          = ctx;
2170   link->next         = NULL;
2171   *p                 = link;
2172   PetscFunctionReturn(0);
2173 }
2174 
2175 #undef __FUNCT__
2176 #define __FUNCT__ "DMRestrict"
2177 /*@
2178    DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd()
2179 
2180    Collective if any hooks are
2181 
2182    Input Arguments:
2183 +  fine - finer DM to use as a base
2184 .  restrct - restriction matrix, apply using MatRestrict()
2185 .  inject - injection matrix, also use MatRestrict()
2186 -  coarse - coarer DM to update
2187 
2188    Level: developer
2189 
2190 .seealso: DMCoarsenHookAdd(), MatRestrict()
2191 @*/
2192 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse)
2193 {
2194   PetscErrorCode    ierr;
2195   DMCoarsenHookLink link;
2196 
2197   PetscFunctionBegin;
2198   for (link=fine->coarsenhook; link; link=link->next) {
2199     if (link->restricthook) {
2200       ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr);
2201     }
2202   }
2203   PetscFunctionReturn(0);
2204 }
2205 
2206 #undef __FUNCT__
2207 #define __FUNCT__ "DMSubDomainHookAdd"
2208 /*@C
2209    DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
2210 
2211    Logically Collective
2212 
2213    Input Arguments:
2214 +  global - global DM
2215 .  ddhook - function to run to pass data to the decomposition DM upon its creation
2216 .  restricthook - function to run to update data on block solve (at the beginning of the block solve)
2217 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2218 
2219 
2220    Calling sequence for ddhook:
2221 $    ddhook(DM global,DM block,void *ctx)
2222 
2223 +  global - global DM
2224 .  block  - block DM
2225 -  ctx - optional user-defined function context
2226 
2227    Calling sequence for restricthook:
2228 $    restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx)
2229 
2230 +  global - global DM
2231 .  out    - scatter to the outer (with ghost and overlap points) block vector
2232 .  in     - scatter to block vector values only owned locally
2233 .  block  - block DM
2234 -  ctx - optional user-defined function context
2235 
2236    Level: advanced
2237 
2238    Notes:
2239    This function is only needed if auxiliary data needs to be set up on subdomain DMs.
2240 
2241    If this function is called multiple times, the hooks will be run in the order they are added.
2242 
2243    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2244    extract the global information from its context (instead of from the SNES).
2245 
2246    This function is currently not available from Fortran.
2247 
2248 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2249 @*/
2250 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
2251 {
2252   PetscErrorCode      ierr;
2253   DMSubDomainHookLink link,*p;
2254 
2255   PetscFunctionBegin;
2256   PetscValidHeaderSpecific(global,DM_CLASSID,1);
2257   for (p=&global->subdomainhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2258   ierr               = PetscMalloc(sizeof(struct _DMSubDomainHookLink),&link);CHKERRQ(ierr);
2259   link->restricthook = restricthook;
2260   link->ddhook       = ddhook;
2261   link->ctx          = ctx;
2262   link->next         = NULL;
2263   *p                 = link;
2264   PetscFunctionReturn(0);
2265 }
2266 
2267 #undef __FUNCT__
2268 #define __FUNCT__ "DMSubDomainRestrict"
2269 /*@
2270    DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd()
2271 
2272    Collective if any hooks are
2273 
2274    Input Arguments:
2275 +  fine - finer DM to use as a base
2276 .  oscatter - scatter from domain global vector filling subdomain global vector with overlap
2277 .  gscatter - scatter from domain global vector filling subdomain local vector with ghosts
2278 -  coarse - coarer DM to update
2279 
2280    Level: developer
2281 
2282 .seealso: DMCoarsenHookAdd(), MatRestrict()
2283 @*/
2284 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm)
2285 {
2286   PetscErrorCode      ierr;
2287   DMSubDomainHookLink link;
2288 
2289   PetscFunctionBegin;
2290   for (link=global->subdomainhook; link; link=link->next) {
2291     if (link->restricthook) {
2292       ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr);
2293     }
2294   }
2295   PetscFunctionReturn(0);
2296 }
2297 
2298 #undef __FUNCT__
2299 #define __FUNCT__ "DMGetCoarsenLevel"
2300 /*@
2301     DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM.
2302 
2303     Not Collective
2304 
2305     Input Parameter:
2306 .   dm - the DM object
2307 
2308     Output Parameter:
2309 .   level - number of coarsenings
2310 
2311     Level: developer
2312 
2313 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2314 
2315 @*/
2316 PetscErrorCode  DMGetCoarsenLevel(DM dm,PetscInt *level)
2317 {
2318   PetscFunctionBegin;
2319   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2320   *level = dm->leveldown;
2321   PetscFunctionReturn(0);
2322 }
2323 
2324 
2325 
2326 #undef __FUNCT__
2327 #define __FUNCT__ "DMRefineHierarchy"
2328 /*@C
2329     DMRefineHierarchy - Refines 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 refinement
2336 
2337     Output Parameter:
2338 .   dmf - the refined DM hierarchy
2339 
2340     Level: developer
2341 
2342 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2343 
2344 @*/
2345 PetscErrorCode  DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
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   if (dm->ops->refinehierarchy) {
2354     ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr);
2355   } else if (dm->ops->refine) {
2356     PetscInt i;
2357 
2358     ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr);
2359     for (i=1; i<nlevels; i++) {
2360       ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr);
2361     }
2362   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
2363   PetscFunctionReturn(0);
2364 }
2365 
2366 #undef __FUNCT__
2367 #define __FUNCT__ "DMCoarsenHierarchy"
2368 /*@C
2369     DMCoarsenHierarchy - Coarsens a DM object, all levels at once
2370 
2371     Collective on DM
2372 
2373     Input Parameter:
2374 +   dm - the DM object
2375 -   nlevels - the number of levels of coarsening
2376 
2377     Output Parameter:
2378 .   dmc - the coarsened DM hierarchy
2379 
2380     Level: developer
2381 
2382 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2383 
2384 @*/
2385 PetscErrorCode  DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
2386 {
2387   PetscErrorCode ierr;
2388 
2389   PetscFunctionBegin;
2390   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2391   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2392   if (nlevels == 0) PetscFunctionReturn(0);
2393   PetscValidPointer(dmc,3);
2394   if (dm->ops->coarsenhierarchy) {
2395     ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr);
2396   } else if (dm->ops->coarsen) {
2397     PetscInt i;
2398 
2399     ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr);
2400     for (i=1; i<nlevels; i++) {
2401       ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr);
2402     }
2403   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
2404   PetscFunctionReturn(0);
2405 }
2406 
2407 #undef __FUNCT__
2408 #define __FUNCT__ "DMCreateAggregates"
2409 /*@
2410    DMCreateAggregates - Gets the aggregates that map between
2411    grids associated with two DMs.
2412 
2413    Collective on DM
2414 
2415    Input Parameters:
2416 +  dmc - the coarse grid DM
2417 -  dmf - the fine grid DM
2418 
2419    Output Parameters:
2420 .  rest - the restriction matrix (transpose of the projection matrix)
2421 
2422    Level: intermediate
2423 
2424 .keywords: interpolation, restriction, multigrid
2425 
2426 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation()
2427 @*/
2428 PetscErrorCode  DMCreateAggregates(DM dmc, DM dmf, Mat *rest)
2429 {
2430   PetscErrorCode ierr;
2431 
2432   PetscFunctionBegin;
2433   PetscValidHeaderSpecific(dmc,DM_CLASSID,1);
2434   PetscValidHeaderSpecific(dmf,DM_CLASSID,2);
2435   ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr);
2436   PetscFunctionReturn(0);
2437 }
2438 
2439 #undef __FUNCT__
2440 #define __FUNCT__ "DMSetApplicationContextDestroy"
2441 /*@C
2442     DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed
2443 
2444     Not Collective
2445 
2446     Input Parameters:
2447 +   dm - the DM object
2448 -   destroy - the destroy function
2449 
2450     Level: intermediate
2451 
2452 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2453 
2454 @*/
2455 PetscErrorCode  DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**))
2456 {
2457   PetscFunctionBegin;
2458   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2459   dm->ctxdestroy = destroy;
2460   PetscFunctionReturn(0);
2461 }
2462 
2463 #undef __FUNCT__
2464 #define __FUNCT__ "DMSetApplicationContext"
2465 /*@
2466     DMSetApplicationContext - Set a user context into a DM object
2467 
2468     Not Collective
2469 
2470     Input Parameters:
2471 +   dm - the DM object
2472 -   ctx - the user context
2473 
2474     Level: intermediate
2475 
2476 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2477 
2478 @*/
2479 PetscErrorCode  DMSetApplicationContext(DM dm,void *ctx)
2480 {
2481   PetscFunctionBegin;
2482   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2483   dm->ctx = ctx;
2484   PetscFunctionReturn(0);
2485 }
2486 
2487 #undef __FUNCT__
2488 #define __FUNCT__ "DMGetApplicationContext"
2489 /*@
2490     DMGetApplicationContext - Gets a user context from a DM object
2491 
2492     Not Collective
2493 
2494     Input Parameter:
2495 .   dm - the DM object
2496 
2497     Output Parameter:
2498 .   ctx - the user context
2499 
2500     Level: intermediate
2501 
2502 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2503 
2504 @*/
2505 PetscErrorCode  DMGetApplicationContext(DM dm,void *ctx)
2506 {
2507   PetscFunctionBegin;
2508   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2509   *(void**)ctx = dm->ctx;
2510   PetscFunctionReturn(0);
2511 }
2512 
2513 #undef __FUNCT__
2514 #define __FUNCT__ "DMSetVariableBounds"
2515 /*@C
2516     DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI.
2517 
2518     Logically Collective on DM
2519 
2520     Input Parameter:
2521 +   dm - the DM object
2522 -   f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set)
2523 
2524     Level: intermediate
2525 
2526 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(),
2527          DMSetJacobian()
2528 
2529 @*/
2530 PetscErrorCode  DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
2531 {
2532   PetscFunctionBegin;
2533   dm->ops->computevariablebounds = f;
2534   PetscFunctionReturn(0);
2535 }
2536 
2537 #undef __FUNCT__
2538 #define __FUNCT__ "DMHasVariableBounds"
2539 /*@
2540     DMHasVariableBounds - does the DM object have a variable bounds function?
2541 
2542     Not Collective
2543 
2544     Input Parameter:
2545 .   dm - the DM object to destroy
2546 
2547     Output Parameter:
2548 .   flg - PETSC_TRUE if the variable bounds function exists
2549 
2550     Level: developer
2551 
2552 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2553 
2554 @*/
2555 PetscErrorCode  DMHasVariableBounds(DM dm,PetscBool  *flg)
2556 {
2557   PetscFunctionBegin;
2558   *flg =  (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
2559   PetscFunctionReturn(0);
2560 }
2561 
2562 #undef __FUNCT__
2563 #define __FUNCT__ "DMComputeVariableBounds"
2564 /*@C
2565     DMComputeVariableBounds - compute variable bounds used by SNESVI.
2566 
2567     Logically Collective on DM
2568 
2569     Input Parameters:
2570 +   dm - the DM object to destroy
2571 -   x  - current solution at which the bounds are computed
2572 
2573     Output parameters:
2574 +   xl - lower bound
2575 -   xu - upper bound
2576 
2577     Level: intermediate
2578 
2579 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2580 
2581 @*/
2582 PetscErrorCode  DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
2583 {
2584   PetscErrorCode ierr;
2585 
2586   PetscFunctionBegin;
2587   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
2588   PetscValidHeaderSpecific(xu,VEC_CLASSID,2);
2589   if (dm->ops->computevariablebounds) {
2590     ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr);
2591   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds.");
2592   PetscFunctionReturn(0);
2593 }
2594 
2595 #undef __FUNCT__
2596 #define __FUNCT__ "DMHasColoring"
2597 /*@
2598     DMHasColoring - does the DM object have a method of providing a coloring?
2599 
2600     Not Collective
2601 
2602     Input Parameter:
2603 .   dm - the DM object
2604 
2605     Output Parameter:
2606 .   flg - PETSC_TRUE if the DM has facilities for DMCreateColoring().
2607 
2608     Level: developer
2609 
2610 .seealso DMHasFunction(), DMCreateColoring()
2611 
2612 @*/
2613 PetscErrorCode  DMHasColoring(DM dm,PetscBool  *flg)
2614 {
2615   PetscFunctionBegin;
2616   *flg =  (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
2617   PetscFunctionReturn(0);
2618 }
2619 
2620 #undef  __FUNCT__
2621 #define __FUNCT__ "DMSetVec"
2622 /*@C
2623     DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear.
2624 
2625     Collective on DM
2626 
2627     Input Parameter:
2628 +   dm - the DM object
2629 -   x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems.
2630 
2631     Level: developer
2632 
2633 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2634 
2635 @*/
2636 PetscErrorCode  DMSetVec(DM dm,Vec x)
2637 {
2638   PetscErrorCode ierr;
2639 
2640   PetscFunctionBegin;
2641   if (x) {
2642     if (!dm->x) {
2643       ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr);
2644     }
2645     ierr = VecCopy(x,dm->x);CHKERRQ(ierr);
2646   } else if (dm->x) {
2647     ierr = VecDestroy(&dm->x);CHKERRQ(ierr);
2648   }
2649   PetscFunctionReturn(0);
2650 }
2651 
2652 PetscFunctionList DMList              = NULL;
2653 PetscBool         DMRegisterAllCalled = PETSC_FALSE;
2654 
2655 #undef __FUNCT__
2656 #define __FUNCT__ "DMSetType"
2657 /*@C
2658   DMSetType - Builds a DM, for a particular DM implementation.
2659 
2660   Collective on DM
2661 
2662   Input Parameters:
2663 + dm     - The DM object
2664 - method - The name of the DM type
2665 
2666   Options Database Key:
2667 . -dm_type <type> - Sets the DM type; use -help for a list of available types
2668 
2669   Notes:
2670   See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).
2671 
2672   Level: intermediate
2673 
2674 .keywords: DM, set, type
2675 .seealso: DMGetType(), DMCreate()
2676 @*/
2677 PetscErrorCode  DMSetType(DM dm, DMType method)
2678 {
2679   PetscErrorCode (*r)(DM);
2680   PetscBool      match;
2681   PetscErrorCode ierr;
2682 
2683   PetscFunctionBegin;
2684   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
2685   ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr);
2686   if (match) PetscFunctionReturn(0);
2687 
2688   if (!DMRegisterAllCalled) {ierr = DMRegisterAll();CHKERRQ(ierr);}
2689   ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr);
2690   if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
2691 
2692   if (dm->ops->destroy) {
2693     ierr             = (*dm->ops->destroy)(dm);CHKERRQ(ierr);
2694     dm->ops->destroy = NULL;
2695   }
2696   ierr = (*r)(dm);CHKERRQ(ierr);
2697   ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr);
2698   PetscFunctionReturn(0);
2699 }
2700 
2701 #undef __FUNCT__
2702 #define __FUNCT__ "DMGetType"
2703 /*@C
2704   DMGetType - Gets the DM type name (as a string) from the DM.
2705 
2706   Not Collective
2707 
2708   Input Parameter:
2709 . dm  - The DM
2710 
2711   Output Parameter:
2712 . type - The DM type name
2713 
2714   Level: intermediate
2715 
2716 .keywords: DM, get, type, name
2717 .seealso: DMSetType(), DMCreate()
2718 @*/
2719 PetscErrorCode  DMGetType(DM dm, DMType *type)
2720 {
2721   PetscErrorCode ierr;
2722 
2723   PetscFunctionBegin;
2724   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
2725   PetscValidPointer(type,2);
2726   if (!DMRegisterAllCalled) {
2727     ierr = DMRegisterAll();CHKERRQ(ierr);
2728   }
2729   *type = ((PetscObject)dm)->type_name;
2730   PetscFunctionReturn(0);
2731 }
2732 
2733 #undef __FUNCT__
2734 #define __FUNCT__ "DMConvert"
2735 /*@C
2736   DMConvert - Converts a DM to another DM, either of the same or different type.
2737 
2738   Collective on DM
2739 
2740   Input Parameters:
2741 + dm - the DM
2742 - newtype - new DM type (use "same" for the same type)
2743 
2744   Output Parameter:
2745 . M - pointer to new DM
2746 
2747   Notes:
2748   Cannot be used to convert a sequential DM to parallel or parallel to sequential,
2749   the MPI communicator of the generated DM is always the same as the communicator
2750   of the input DM.
2751 
2752   Level: intermediate
2753 
2754 .seealso: DMCreate()
2755 @*/
2756 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
2757 {
2758   DM             B;
2759   char           convname[256];
2760   PetscBool      sametype, issame;
2761   PetscErrorCode ierr;
2762 
2763   PetscFunctionBegin;
2764   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2765   PetscValidType(dm,1);
2766   PetscValidPointer(M,3);
2767   ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr);
2768   ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr);
2769   {
2770     PetscErrorCode (*conv)(DM, DMType, DM*) = NULL;
2771 
2772     /*
2773        Order of precedence:
2774        1) See if a specialized converter is known to the current DM.
2775        2) See if a specialized converter is known to the desired DM class.
2776        3) See if a good general converter is registered for the desired class
2777        4) See if a good general converter is known for the current matrix.
2778        5) Use a really basic converter.
2779     */
2780 
2781     /* 1) See if a specialized converter is known to the current DM and the desired class */
2782     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
2783     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
2784     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
2785     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
2786     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
2787     ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr);
2788     if (conv) goto foundconv;
2789 
2790     /* 2)  See if a specialized converter is known to the desired DM class. */
2791     ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr);
2792     ierr = DMSetType(B, newtype);CHKERRQ(ierr);
2793     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
2794     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
2795     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
2796     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
2797     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
2798     ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr);
2799     if (conv) {
2800       ierr = DMDestroy(&B);CHKERRQ(ierr);
2801       goto foundconv;
2802     }
2803 
2804 #if 0
2805     /* 3) See if a good general converter is registered for the desired class */
2806     conv = B->ops->convertfrom;
2807     ierr = DMDestroy(&B);CHKERRQ(ierr);
2808     if (conv) goto foundconv;
2809 
2810     /* 4) See if a good general converter is known for the current matrix */
2811     if (dm->ops->convert) {
2812       conv = dm->ops->convert;
2813     }
2814     if (conv) goto foundconv;
2815 #endif
2816 
2817     /* 5) Use a really basic converter. */
2818     SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);
2819 
2820 foundconv:
2821     ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
2822     ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr);
2823     ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
2824   }
2825   ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr);
2826   PetscFunctionReturn(0);
2827 }
2828 
2829 /*--------------------------------------------------------------------------------------------------------------------*/
2830 
2831 #undef __FUNCT__
2832 #define __FUNCT__ "DMRegister"
2833 /*@C
2834   DMRegister -  Adds a new DM component implementation
2835 
2836   Not Collective
2837 
2838   Input Parameters:
2839 + name        - The name of a new user-defined creation routine
2840 - create_func - The creation routine itself
2841 
2842   Notes:
2843   DMRegister() may be called multiple times to add several user-defined DMs
2844 
2845 
2846   Sample usage:
2847 .vb
2848     DMRegister("my_da", MyDMCreate);
2849 .ve
2850 
2851   Then, your DM type can be chosen with the procedural interface via
2852 .vb
2853     DMCreate(MPI_Comm, DM *);
2854     DMSetType(DM,"my_da");
2855 .ve
2856    or at runtime via the option
2857 .vb
2858     -da_type my_da
2859 .ve
2860 
2861   Level: advanced
2862 
2863 .keywords: DM, register
2864 .seealso: DMRegisterAll(), DMRegisterDestroy()
2865 
2866 @*/
2867 PetscErrorCode  DMRegister(const char sname[],PetscErrorCode (*function)(DM))
2868 {
2869   PetscErrorCode ierr;
2870 
2871   PetscFunctionBegin;
2872   ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr);
2873   PetscFunctionReturn(0);
2874 }
2875 
2876 #undef __FUNCT__
2877 #define __FUNCT__ "DMLoad"
2878 /*@C
2879   DMLoad - Loads a DM that has been stored in binary  with DMView().
2880 
2881   Collective on PetscViewer
2882 
2883   Input Parameters:
2884 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
2885            some related function before a call to DMLoad().
2886 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
2887            HDF5 file viewer, obtained from PetscViewerHDF5Open()
2888 
2889    Level: intermediate
2890 
2891   Notes:
2892    The type is determined by the data in the file, any type set into the DM before this call is ignored.
2893 
2894   Notes for advanced users:
2895   Most users should not need to know the details of the binary storage
2896   format, since DMLoad() and DMView() completely hide these details.
2897   But for anyone who's interested, the standard binary matrix storage
2898   format is
2899 .vb
2900      has not yet been determined
2901 .ve
2902 
2903 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad()
2904 @*/
2905 PetscErrorCode  DMLoad(DM newdm, PetscViewer viewer)
2906 {
2907   PetscBool      isbinary, ishdf5;
2908   PetscErrorCode ierr;
2909 
2910   PetscFunctionBegin;
2911   PetscValidHeaderSpecific(newdm,DM_CLASSID,1);
2912   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
2913   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
2914   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
2915   if (isbinary) {
2916     PetscInt classid;
2917     char     type[256];
2918 
2919     ierr = PetscViewerBinaryRead(viewer,&classid,1,PETSC_INT);CHKERRQ(ierr);
2920     if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid);
2921     ierr = PetscViewerBinaryRead(viewer,type,256,PETSC_CHAR);CHKERRQ(ierr);
2922     ierr = DMSetType(newdm, type);CHKERRQ(ierr);
2923     if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);}
2924   } else if (ishdf5) {
2925     if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);}
2926   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
2927   PetscFunctionReturn(0);
2928 }
2929 
2930 /******************************** FEM Support **********************************/
2931 
2932 #undef __FUNCT__
2933 #define __FUNCT__ "DMPrintCellVector"
2934 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
2935 {
2936   PetscInt       f;
2937   PetscErrorCode ierr;
2938 
2939   PetscFunctionBegin;
2940   ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
2941   for (f = 0; f < len; ++f) {
2942     ierr = PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr);
2943   }
2944   PetscFunctionReturn(0);
2945 }
2946 
2947 #undef __FUNCT__
2948 #define __FUNCT__ "DMPrintCellMatrix"
2949 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
2950 {
2951   PetscInt       f, g;
2952   PetscErrorCode ierr;
2953 
2954   PetscFunctionBegin;
2955   ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
2956   for (f = 0; f < rows; ++f) {
2957     ierr = PetscPrintf(PETSC_COMM_SELF, "  |");CHKERRQ(ierr);
2958     for (g = 0; g < cols; ++g) {
2959       ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr);
2960     }
2961     ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr);
2962   }
2963   PetscFunctionReturn(0);
2964 }
2965 
2966 #undef __FUNCT__
2967 #define __FUNCT__ "DMPrintLocalVec"
2968 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
2969 {
2970   PetscMPIInt    rank, numProcs;
2971   PetscInt       p;
2972   PetscErrorCode ierr;
2973 
2974   PetscFunctionBegin;
2975   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr);
2976   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr);
2977   ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "%s:\n", name);CHKERRQ(ierr);
2978   for (p = 0; p < numProcs; ++p) {
2979     if (p == rank) {
2980       Vec x;
2981 
2982       ierr = VecDuplicate(X, &x);CHKERRQ(ierr);
2983       ierr = VecCopy(X, x);CHKERRQ(ierr);
2984       ierr = VecChop(x, tol);CHKERRQ(ierr);
2985       ierr = VecView(x, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2986       ierr = VecDestroy(&x);CHKERRQ(ierr);
2987       ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2988     }
2989     ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr);
2990   }
2991   PetscFunctionReturn(0);
2992 }
2993 
2994 #undef __FUNCT__
2995 #define __FUNCT__ "DMGetDefaultSection"
2996 /*@
2997   DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM.
2998 
2999   Input Parameter:
3000 . dm - The DM
3001 
3002   Output Parameter:
3003 . section - The PetscSection
3004 
3005   Level: intermediate
3006 
3007   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3008 
3009 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
3010 @*/
3011 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section)
3012 {
3013   PetscErrorCode ierr;
3014 
3015   PetscFunctionBegin;
3016   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3017   PetscValidPointer(section, 2);
3018   if (!dm->defaultSection && dm->ops->createdefaultsection) {
3019     ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr);
3020     ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, "dm_", "-petscsection_view");CHKERRQ(ierr);
3021   }
3022   *section = dm->defaultSection;
3023   PetscFunctionReturn(0);
3024 }
3025 
3026 #undef __FUNCT__
3027 #define __FUNCT__ "DMSetDefaultSection"
3028 /*@
3029   DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM.
3030 
3031   Input Parameters:
3032 + dm - The DM
3033 - section - The PetscSection
3034 
3035   Level: intermediate
3036 
3037   Note: Any existing Section will be destroyed
3038 
3039 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
3040 @*/
3041 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section)
3042 {
3043   PetscInt       numFields;
3044   PetscInt       f;
3045   PetscErrorCode ierr;
3046 
3047   PetscFunctionBegin;
3048   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3049   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
3050   ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
3051   ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr);
3052   dm->defaultSection = section;
3053   ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);
3054   if (numFields) {
3055     ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr);
3056     for (f = 0; f < numFields; ++f) {
3057       PetscObject disc;
3058       const char *name;
3059 
3060       ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr);
3061       ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr);
3062       ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr);
3063     }
3064   }
3065   /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */
3066   ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr);
3067   PetscFunctionReturn(0);
3068 }
3069 
3070 #undef __FUNCT__
3071 #define __FUNCT__ "DMGetDefaultConstraints"
3072 /*@
3073   DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation.
3074 
3075   not collective
3076 
3077   Input Parameter:
3078 . dm - The DM
3079 
3080   Output Parameter:
3081 + 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.
3082 - 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.
3083 
3084   Level: advanced
3085 
3086   Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat.
3087 
3088 .seealso: DMSetDefaultConstraints()
3089 @*/
3090 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat)
3091 {
3092   PetscErrorCode ierr;
3093 
3094   PetscFunctionBegin;
3095   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3096   if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);}
3097   if (section) {*section = dm->defaultConstraintSection;}
3098   if (mat) {*mat = dm->defaultConstraintMat;}
3099   PetscFunctionReturn(0);
3100 }
3101 
3102 #undef __FUNCT__
3103 #define __FUNCT__ "DMSetDefaultConstraints"
3104 /*@
3105   DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation.
3106 
3107   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().
3108 
3109   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.
3110 
3111   collective on dm
3112 
3113   Input Parameters:
3114 + dm - The DM
3115 + 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).
3116 - 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).
3117 
3118   Level: advanced
3119 
3120   Note: This increments the references of the PetscSection and the Mat, so they user can destroy them
3121 
3122 .seealso: DMGetDefaultConstraints()
3123 @*/
3124 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat)
3125 {
3126   PetscMPIInt result;
3127   PetscErrorCode ierr;
3128 
3129   PetscFunctionBegin;
3130   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3131   if (section) {
3132     PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
3133     ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr);
3134     if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator");
3135   }
3136   if (mat) {
3137     PetscValidHeaderSpecific(mat,MAT_CLASSID,3);
3138     ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr);
3139     if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator");
3140   }
3141   ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
3142   ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr);
3143   dm->defaultConstraintSection = section;
3144   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
3145   ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr);
3146   dm->defaultConstraintMat = mat;
3147   PetscFunctionReturn(0);
3148 }
3149 
3150 #undef __FUNCT__
3151 #define __FUNCT__ "DMGetDefaultGlobalSection"
3152 /*@
3153   DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM.
3154 
3155   Collective on DM
3156 
3157   Input Parameter:
3158 . dm - The DM
3159 
3160   Output Parameter:
3161 . section - The PetscSection
3162 
3163   Level: intermediate
3164 
3165   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3166 
3167 .seealso: DMSetDefaultSection(), DMGetDefaultSection()
3168 @*/
3169 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section)
3170 {
3171   PetscErrorCode ierr;
3172 
3173   PetscFunctionBegin;
3174   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3175   PetscValidPointer(section, 2);
3176   if (!dm->defaultGlobalSection) {
3177     PetscSection s;
3178 
3179     ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
3180     if (!s)  SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
3181     if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection");
3182     ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr);
3183     ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr);
3184     ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr);
3185   }
3186   *section = dm->defaultGlobalSection;
3187   PetscFunctionReturn(0);
3188 }
3189 
3190 #undef __FUNCT__
3191 #define __FUNCT__ "DMSetDefaultGlobalSection"
3192 /*@
3193   DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM.
3194 
3195   Input Parameters:
3196 + dm - The DM
3197 - section - The PetscSection, or NULL
3198 
3199   Level: intermediate
3200 
3201   Note: Any existing Section will be destroyed
3202 
3203 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection()
3204 @*/
3205 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section)
3206 {
3207   PetscErrorCode ierr;
3208 
3209   PetscFunctionBegin;
3210   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3211   if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
3212   ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
3213   ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr);
3214   dm->defaultGlobalSection = section;
3215   PetscFunctionReturn(0);
3216 }
3217 
3218 #undef __FUNCT__
3219 #define __FUNCT__ "DMGetDefaultSF"
3220 /*@
3221   DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set,
3222   it is created from the default PetscSection layouts in the DM.
3223 
3224   Input Parameter:
3225 . dm - The DM
3226 
3227   Output Parameter:
3228 . sf - The PetscSF
3229 
3230   Level: intermediate
3231 
3232   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3233 
3234 .seealso: DMSetDefaultSF(), DMCreateDefaultSF()
3235 @*/
3236 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf)
3237 {
3238   PetscInt       nroots;
3239   PetscErrorCode ierr;
3240 
3241   PetscFunctionBegin;
3242   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3243   PetscValidPointer(sf, 2);
3244   ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
3245   if (nroots < 0) {
3246     PetscSection section, gSection;
3247 
3248     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
3249     if (section) {
3250       ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr);
3251       ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr);
3252     } else {
3253       *sf = NULL;
3254       PetscFunctionReturn(0);
3255     }
3256   }
3257   *sf = dm->defaultSF;
3258   PetscFunctionReturn(0);
3259 }
3260 
3261 #undef __FUNCT__
3262 #define __FUNCT__ "DMSetDefaultSF"
3263 /*@
3264   DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM
3265 
3266   Input Parameters:
3267 + dm - The DM
3268 - sf - The PetscSF
3269 
3270   Level: intermediate
3271 
3272   Note: Any previous SF is destroyed
3273 
3274 .seealso: DMGetDefaultSF(), DMCreateDefaultSF()
3275 @*/
3276 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf)
3277 {
3278   PetscErrorCode ierr;
3279 
3280   PetscFunctionBegin;
3281   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3282   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
3283   ierr          = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr);
3284   dm->defaultSF = sf;
3285   PetscFunctionReturn(0);
3286 }
3287 
3288 #undef __FUNCT__
3289 #define __FUNCT__ "DMCreateDefaultSF"
3290 /*@C
3291   DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections
3292   describing the data layout.
3293 
3294   Input Parameters:
3295 + dm - The DM
3296 . localSection - PetscSection describing the local data layout
3297 - globalSection - PetscSection describing the global data layout
3298 
3299   Level: intermediate
3300 
3301 .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3302 @*/
3303 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection)
3304 {
3305   MPI_Comm       comm;
3306   PetscLayout    layout;
3307   const PetscInt *ranges;
3308   PetscInt       *local;
3309   PetscSFNode    *remote;
3310   PetscInt       pStart, pEnd, p, nroots, nleaves = 0, l;
3311   PetscMPIInt    size, rank;
3312   PetscErrorCode ierr;
3313 
3314   PetscFunctionBegin;
3315   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
3316   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3317   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
3318   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3319   ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr);
3320   ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr);
3321   ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
3322   ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
3323   ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr);
3324   ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
3325   ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
3326   for (p = pStart; p < pEnd; ++p) {
3327     PetscInt gdof, gcdof;
3328 
3329     ierr     = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3330     ierr     = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3331     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));
3332     nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3333   }
3334   ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr);
3335   ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr);
3336   for (p = pStart, l = 0; p < pEnd; ++p) {
3337     const PetscInt *cind;
3338     PetscInt       dof, cdof, off, gdof, gcdof, goff, gsize, d, c;
3339 
3340     ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr);
3341     ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr);
3342     ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr);
3343     ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr);
3344     ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3345     ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3346     ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr);
3347     if (!gdof) continue; /* Censored point */
3348     gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3349     if (gsize != dof-cdof) {
3350       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);
3351       cdof = 0; /* Ignore constraints */
3352     }
3353     for (d = 0, c = 0; d < dof; ++d) {
3354       if ((c < cdof) && (cind[c] == d)) {++c; continue;}
3355       local[l+d-c] = off+d;
3356     }
3357     if (gdof < 0) {
3358       for (d = 0; d < gsize; ++d, ++l) {
3359         PetscInt offset = -(goff+1) + d, r;
3360 
3361         ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr);
3362         if (r < 0) r = -(r+2);
3363         if ((r < 0) || (r >= size)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d mapped to invalid process %d (%d, %d)", p, r, gdof, goff);
3364         remote[l].rank  = r;
3365         remote[l].index = offset - ranges[r];
3366       }
3367     } else {
3368       for (d = 0; d < gsize; ++d, ++l) {
3369         remote[l].rank  = rank;
3370         remote[l].index = goff+d - ranges[rank];
3371       }
3372     }
3373   }
3374   if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves);
3375   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
3376   ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr);
3377   PetscFunctionReturn(0);
3378 }
3379 
3380 #undef __FUNCT__
3381 #define __FUNCT__ "DMGetPointSF"
3382 /*@
3383   DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM.
3384 
3385   Input Parameter:
3386 . dm - The DM
3387 
3388   Output Parameter:
3389 . sf - The PetscSF
3390 
3391   Level: intermediate
3392 
3393   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3394 
3395 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3396 @*/
3397 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
3398 {
3399   PetscFunctionBegin;
3400   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3401   PetscValidPointer(sf, 2);
3402   *sf = dm->sf;
3403   PetscFunctionReturn(0);
3404 }
3405 
3406 #undef __FUNCT__
3407 #define __FUNCT__ "DMSetPointSF"
3408 /*@
3409   DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM.
3410 
3411   Input Parameters:
3412 + dm - The DM
3413 - sf - The PetscSF
3414 
3415   Level: intermediate
3416 
3417 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3418 @*/
3419 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
3420 {
3421   PetscErrorCode ierr;
3422 
3423   PetscFunctionBegin;
3424   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3425   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
3426   ierr   = PetscSFDestroy(&dm->sf);CHKERRQ(ierr);
3427   ierr   = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr);
3428   dm->sf = sf;
3429   PetscFunctionReturn(0);
3430 }
3431 
3432 #undef __FUNCT__
3433 #define __FUNCT__ "DMGetDS"
3434 /*@
3435   DMGetDS - Get the PetscDS
3436 
3437   Input Parameter:
3438 . dm - The DM
3439 
3440   Output Parameter:
3441 . prob - The PetscDS
3442 
3443   Level: developer
3444 
3445 .seealso: DMSetDS()
3446 @*/
3447 PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
3448 {
3449   PetscFunctionBegin;
3450   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3451   PetscValidPointer(prob, 2);
3452   *prob = dm->prob;
3453   PetscFunctionReturn(0);
3454 }
3455 
3456 #undef __FUNCT__
3457 #define __FUNCT__ "DMSetDS"
3458 /*@
3459   DMSetDS - Set the PetscDS
3460 
3461   Input Parameters:
3462 + dm - The DM
3463 - prob - The PetscDS
3464 
3465   Level: developer
3466 
3467 .seealso: DMGetDS()
3468 @*/
3469 PetscErrorCode DMSetDS(DM dm, PetscDS prob)
3470 {
3471   PetscErrorCode ierr;
3472 
3473   PetscFunctionBegin;
3474   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3475   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2);
3476   ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr);
3477   dm->prob = prob;
3478   ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr);
3479   PetscFunctionReturn(0);
3480 }
3481 
3482 #undef __FUNCT__
3483 #define __FUNCT__ "DMGetNumFields"
3484 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
3485 {
3486   PetscErrorCode ierr;
3487 
3488   PetscFunctionBegin;
3489   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3490   ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr);
3491   PetscFunctionReturn(0);
3492 }
3493 
3494 #undef __FUNCT__
3495 #define __FUNCT__ "DMSetNumFields"
3496 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
3497 {
3498   PetscInt       Nf, f;
3499   PetscErrorCode ierr;
3500 
3501   PetscFunctionBegin;
3502   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3503   ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr);
3504   for (f = Nf; f < numFields; ++f) {
3505     PetscContainer obj;
3506 
3507     ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr);
3508     ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr);
3509     ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr);
3510   }
3511   PetscFunctionReturn(0);
3512 }
3513 
3514 #undef __FUNCT__
3515 #define __FUNCT__ "DMGetField"
3516 /*@
3517   DMGetField - Return the discretization object for a given DM field
3518 
3519   Not collective
3520 
3521   Input Parameters:
3522 + dm - The DM
3523 - f  - The field number
3524 
3525   Output Parameter:
3526 . field - The discretization object
3527 
3528   Level: developer
3529 
3530 .seealso: DMSetField()
3531 @*/
3532 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field)
3533 {
3534   PetscErrorCode ierr;
3535 
3536   PetscFunctionBegin;
3537   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3538   ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr);
3539   PetscFunctionReturn(0);
3540 }
3541 
3542 #undef __FUNCT__
3543 #define __FUNCT__ "DMSetField"
3544 /*@
3545   DMSetField - Set the discretization object for a given DM field
3546 
3547   Logically collective on DM
3548 
3549   Input Parameters:
3550 + dm - The DM
3551 . f  - The field number
3552 - field - The discretization object
3553 
3554   Level: developer
3555 
3556 .seealso: DMGetField()
3557 @*/
3558 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field)
3559 {
3560   PetscErrorCode ierr;
3561 
3562   PetscFunctionBegin;
3563   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3564   ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr);
3565   PetscFunctionReturn(0);
3566 }
3567 
3568 #undef __FUNCT__
3569 #define __FUNCT__ "DMRestrictHook_Coordinates"
3570 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx)
3571 {
3572   DM dm_coord,dmc_coord;
3573   PetscErrorCode ierr;
3574   Vec coords,ccoords;
3575   VecScatter scat;
3576   PetscFunctionBegin;
3577   ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr);
3578   ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr);
3579   ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
3580   ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr);
3581   if (coords && !ccoords) {
3582     ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr);
3583     ierr = DMCreateInjection(dmc_coord,dm_coord,&scat);CHKERRQ(ierr);
3584     ierr = VecScatterBegin(scat,coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3585     ierr = VecScatterEnd(scat,coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3586     ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr);
3587     ierr = VecScatterDestroy(&scat);CHKERRQ(ierr);
3588     ierr = VecDestroy(&ccoords);CHKERRQ(ierr);
3589   }
3590   PetscFunctionReturn(0);
3591 }
3592 
3593 #undef __FUNCT__
3594 #define __FUNCT__ "DMSubDomainHook_Coordinates"
3595 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx)
3596 {
3597   DM dm_coord,subdm_coord;
3598   PetscErrorCode ierr;
3599   Vec coords,ccoords,clcoords;
3600   VecScatter *scat_i,*scat_g;
3601   PetscFunctionBegin;
3602   ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr);
3603   ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr);
3604   ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
3605   ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr);
3606   if (coords && !ccoords) {
3607     ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr);
3608     ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr);
3609     ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr);
3610     ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3611     ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3612     ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3613     ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3614     ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr);
3615     ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr);
3616     ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr);
3617     ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr);
3618     ierr = VecDestroy(&ccoords);CHKERRQ(ierr);
3619     ierr = VecDestroy(&clcoords);CHKERRQ(ierr);
3620     ierr = PetscFree(scat_i);CHKERRQ(ierr);
3621     ierr = PetscFree(scat_g);CHKERRQ(ierr);
3622   }
3623   PetscFunctionReturn(0);
3624 }
3625 
3626 #undef __FUNCT__
3627 #define __FUNCT__ "DMGetDimension"
3628 /*@
3629   DMGetDimension - Return the topological dimension of the DM
3630 
3631   Not collective
3632 
3633   Input Parameter:
3634 . dm - The DM
3635 
3636   Output Parameter:
3637 . dim - The topological dimension
3638 
3639   Level: beginner
3640 
3641 .seealso: DMSetDimension(), DMCreate()
3642 @*/
3643 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
3644 {
3645   PetscFunctionBegin;
3646   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3647   PetscValidPointer(dim, 2);
3648   *dim = dm->dim;
3649   PetscFunctionReturn(0);
3650 }
3651 
3652 #undef __FUNCT__
3653 #define __FUNCT__ "DMSetDimension"
3654 /*@
3655   DMSetDimension - Set the topological dimension of the DM
3656 
3657   Collective on dm
3658 
3659   Input Parameters:
3660 + dm - The DM
3661 - dim - The topological dimension
3662 
3663   Level: beginner
3664 
3665 .seealso: DMGetDimension(), DMCreate()
3666 @*/
3667 PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
3668 {
3669   PetscFunctionBegin;
3670   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3671   PetscValidLogicalCollectiveInt(dm, dim, 2);
3672   dm->dim = dim;
3673   PetscFunctionReturn(0);
3674 }
3675 
3676 #undef __FUNCT__
3677 #define __FUNCT__ "DMGetDimPoints"
3678 /*@
3679   DMGetDimPoints - Get the half-open interval for all points of a given dimension
3680 
3681   Collective on DM
3682 
3683   Input Parameters:
3684 + dm - the DM
3685 - dim - the dimension
3686 
3687   Output Parameters:
3688 + pStart - The first point of the given dimension
3689 . pEnd - The first point following points of the given dimension
3690 
3691   Note:
3692   The points are vertices in the Hasse diagram encoding the topology. This is explained in
3693   http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme,
3694   then the interval is empty.
3695 
3696   Level: intermediate
3697 
3698 .keywords: point, Hasse Diagram, dimension
3699 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum()
3700 @*/
3701 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
3702 {
3703   PetscInt       d;
3704   PetscErrorCode ierr;
3705 
3706   PetscFunctionBegin;
3707   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3708   ierr = DMGetDimension(dm, &d);CHKERRQ(ierr);
3709   if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d);
3710   ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr);
3711   PetscFunctionReturn(0);
3712 }
3713 
3714 #undef __FUNCT__
3715 #define __FUNCT__ "DMSetCoordinates"
3716 /*@
3717   DMSetCoordinates - Sets into the DM a global vector that holds the coordinates
3718 
3719   Collective on DM
3720 
3721   Input Parameters:
3722 + dm - the DM
3723 - c - coordinate vector
3724 
3725   Note:
3726   The coordinates do include those for ghost points, which are in the local vector
3727 
3728   Level: intermediate
3729 
3730 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3731 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM()
3732 @*/
3733 PetscErrorCode DMSetCoordinates(DM dm, Vec c)
3734 {
3735   PetscErrorCode ierr;
3736 
3737   PetscFunctionBegin;
3738   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3739   PetscValidHeaderSpecific(c,VEC_CLASSID,2);
3740   ierr            = PetscObjectReference((PetscObject) c);CHKERRQ(ierr);
3741   ierr            = VecDestroy(&dm->coordinates);CHKERRQ(ierr);
3742   dm->coordinates = c;
3743   ierr            = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr);
3744   ierr            = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr);
3745   ierr            = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr);
3746   PetscFunctionReturn(0);
3747 }
3748 
3749 #undef __FUNCT__
3750 #define __FUNCT__ "DMSetCoordinatesLocal"
3751 /*@
3752   DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates
3753 
3754   Collective on DM
3755 
3756    Input Parameters:
3757 +  dm - the DM
3758 -  c - coordinate vector
3759 
3760   Note:
3761   The coordinates of ghost points can be set using DMSetCoordinates()
3762   followed by DMGetCoordinatesLocal(). This is intended to enable the
3763   setting of ghost coordinates outside of the domain.
3764 
3765   Level: intermediate
3766 
3767 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3768 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM()
3769 @*/
3770 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c)
3771 {
3772   PetscErrorCode ierr;
3773 
3774   PetscFunctionBegin;
3775   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3776   PetscValidHeaderSpecific(c,VEC_CLASSID,2);
3777   ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr);
3778   ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr);
3779 
3780   dm->coordinatesLocal = c;
3781 
3782   ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr);
3783   PetscFunctionReturn(0);
3784 }
3785 
3786 #undef __FUNCT__
3787 #define __FUNCT__ "DMGetCoordinates"
3788 /*@
3789   DMGetCoordinates - Gets a global vector with the coordinates associated with the DM.
3790 
3791   Not Collective
3792 
3793   Input Parameter:
3794 . dm - the DM
3795 
3796   Output Parameter:
3797 . c - global coordinate vector
3798 
3799   Note:
3800   This is a borrowed reference, so the user should NOT destroy this vector
3801 
3802   Each process has only the local coordinates (does NOT have the ghost coordinates).
3803 
3804   For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
3805   and (x_0,y_0,z_0,x_1,y_1,z_1...)
3806 
3807   Level: intermediate
3808 
3809 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3810 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
3811 @*/
3812 PetscErrorCode DMGetCoordinates(DM dm, Vec *c)
3813 {
3814   PetscErrorCode ierr;
3815 
3816   PetscFunctionBegin;
3817   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3818   PetscValidPointer(c,2);
3819   if (!dm->coordinates && dm->coordinatesLocal) {
3820     DM cdm = NULL;
3821 
3822     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
3823     ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr);
3824     ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr);
3825     ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr);
3826     ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr);
3827   }
3828   *c = dm->coordinates;
3829   PetscFunctionReturn(0);
3830 }
3831 
3832 #undef __FUNCT__
3833 #define __FUNCT__ "DMGetCoordinatesLocal"
3834 /*@
3835   DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM.
3836 
3837   Collective on DM
3838 
3839   Input Parameter:
3840 . dm - the DM
3841 
3842   Output Parameter:
3843 . c - coordinate vector
3844 
3845   Note:
3846   This is a borrowed reference, so the user should NOT destroy this vector
3847 
3848   Each process has the local and ghost coordinates
3849 
3850   For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
3851   and (x_0,y_0,z_0,x_1,y_1,z_1...)
3852 
3853   Level: intermediate
3854 
3855 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3856 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM()
3857 @*/
3858 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c)
3859 {
3860   PetscErrorCode ierr;
3861 
3862   PetscFunctionBegin;
3863   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3864   PetscValidPointer(c,2);
3865   if (!dm->coordinatesLocal && dm->coordinates) {
3866     DM cdm = NULL;
3867 
3868     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
3869     ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr);
3870     ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr);
3871     ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr);
3872     ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr);
3873   }
3874   *c = dm->coordinatesLocal;
3875   PetscFunctionReturn(0);
3876 }
3877 
3878 #undef __FUNCT__
3879 #define __FUNCT__ "DMGetCoordinateDM"
3880 /*@
3881   DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates
3882 
3883   Collective on DM
3884 
3885   Input Parameter:
3886 . dm - the DM
3887 
3888   Output Parameter:
3889 . cdm - coordinate DM
3890 
3891   Level: intermediate
3892 
3893 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3894 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
3895 @*/
3896 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm)
3897 {
3898   PetscErrorCode ierr;
3899 
3900   PetscFunctionBegin;
3901   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3902   PetscValidPointer(cdm,2);
3903   if (!dm->coordinateDM) {
3904     if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM");
3905     ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr);
3906   }
3907   *cdm = dm->coordinateDM;
3908   PetscFunctionReturn(0);
3909 }
3910 
3911 #undef __FUNCT__
3912 #define __FUNCT__ "DMSetCoordinateDM"
3913 /*@
3914   DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates
3915 
3916   Logically Collective on DM
3917 
3918   Input Parameters:
3919 + dm - the DM
3920 - cdm - coordinate DM
3921 
3922   Level: intermediate
3923 
3924 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3925 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
3926 @*/
3927 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm)
3928 {
3929   PetscErrorCode ierr;
3930 
3931   PetscFunctionBegin;
3932   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3933   PetscValidHeaderSpecific(cdm,DM_CLASSID,2);
3934   ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr);
3935   dm->coordinateDM = cdm;
3936   ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr);
3937   PetscFunctionReturn(0);
3938 }
3939 
3940 #undef __FUNCT__
3941 #define __FUNCT__ "DMGetCoordinateDim"
3942 /*@
3943   DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values.
3944 
3945   Not Collective
3946 
3947   Input Parameter:
3948 . dm - The DM object
3949 
3950   Output Parameter:
3951 . dim - The embedding dimension
3952 
3953   Level: intermediate
3954 
3955 .keywords: mesh, coordinates
3956 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
3957 @*/
3958 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim)
3959 {
3960   PetscFunctionBegin;
3961   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3962   PetscValidPointer(dim, 2);
3963   if (dm->dimEmbed == PETSC_DEFAULT) {
3964     dm->dimEmbed = dm->dim;
3965   }
3966   *dim = dm->dimEmbed;
3967   PetscFunctionReturn(0);
3968 }
3969 
3970 #undef __FUNCT__
3971 #define __FUNCT__ "DMSetCoordinateDim"
3972 /*@
3973   DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values.
3974 
3975   Not Collective
3976 
3977   Input Parameters:
3978 + dm  - The DM object
3979 - dim - The embedding dimension
3980 
3981   Level: intermediate
3982 
3983 .keywords: mesh, coordinates
3984 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
3985 @*/
3986 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim)
3987 {
3988   PetscFunctionBegin;
3989   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3990   dm->dimEmbed = dim;
3991   PetscFunctionReturn(0);
3992 }
3993 
3994 #undef __FUNCT__
3995 #define __FUNCT__ "DMGetCoordinateSection"
3996 /*@
3997   DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh.
3998 
3999   Not Collective
4000 
4001   Input Parameter:
4002 . dm - The DM object
4003 
4004   Output Parameter:
4005 . section - The PetscSection object
4006 
4007   Level: intermediate
4008 
4009 .keywords: mesh, coordinates
4010 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
4011 @*/
4012 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section)
4013 {
4014   DM             cdm;
4015   PetscErrorCode ierr;
4016 
4017   PetscFunctionBegin;
4018   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4019   PetscValidPointer(section, 2);
4020   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
4021   ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr);
4022   PetscFunctionReturn(0);
4023 }
4024 
4025 #undef __FUNCT__
4026 #define __FUNCT__ "DMSetCoordinateSection"
4027 /*@
4028   DMSetCoordinateSection - Set the layout of coordinate values over the mesh.
4029 
4030   Not Collective
4031 
4032   Input Parameters:
4033 + dm      - The DM object
4034 . dim     - The embedding dimension, or PETSC_DETERMINE
4035 - section - The PetscSection object
4036 
4037   Level: intermediate
4038 
4039 .keywords: mesh, coordinates
4040 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
4041 @*/
4042 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section)
4043 {
4044   DM             cdm;
4045   PetscErrorCode ierr;
4046 
4047   PetscFunctionBegin;
4048   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4049   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3);
4050   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
4051   ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr);
4052   if (dim == PETSC_DETERMINE) {
4053     PetscInt d = dim;
4054     PetscInt pStart, pEnd, vStart, vEnd, v, dd;
4055 
4056     ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
4057     ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
4058     pStart = PetscMax(vStart, pStart);
4059     pEnd   = PetscMin(vEnd, pEnd);
4060     for (v = pStart; v < pEnd; ++v) {
4061       ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr);
4062       if (dd) {d = dd; break;}
4063     }
4064     ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);
4065   }
4066   PetscFunctionReturn(0);
4067 }
4068 
4069 #undef __FUNCT__
4070 #define __FUNCT__ "DMGetPeriodicity"
4071 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L)
4072 {
4073   PetscFunctionBegin;
4074   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4075   if (L)       *L       = dm->L;
4076   if (maxCell) *maxCell = dm->maxCell;
4077   PetscFunctionReturn(0);
4078 }
4079 
4080 #undef __FUNCT__
4081 #define __FUNCT__ "DMSetPeriodicity"
4082 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[])
4083 {
4084   Vec            coordinates;
4085   PetscInt       dim, d;
4086   PetscErrorCode ierr;
4087 
4088   PetscFunctionBegin;
4089   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4090   ierr = PetscFree(dm->L);CHKERRQ(ierr);
4091   ierr = PetscFree(dm->maxCell);CHKERRQ(ierr);
4092   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
4093   ierr = VecGetBlockSize(coordinates, &dim);CHKERRQ(ierr);
4094   ierr = PetscMalloc1(dim,&dm->L);CHKERRQ(ierr);
4095   ierr = PetscMalloc1(dim,&dm->maxCell);CHKERRQ(ierr);
4096   for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d];}
4097   PetscFunctionReturn(0);
4098 }
4099 
4100 #undef __FUNCT__
4101 #define __FUNCT__ "DMLocatePoints"
4102 /*@
4103   DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells
4104 
4105   Not collective
4106 
4107   Input Parameters:
4108 + dm - The DM
4109 - v - The Vec of points
4110 
4111   Output Parameter:
4112 . cells - The local cell numbers for cells which contain the points
4113 
4114   Level: developer
4115 
4116 .keywords: point location, mesh
4117 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4118 @*/
4119 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells)
4120 {
4121   PetscErrorCode ierr;
4122 
4123   PetscFunctionBegin;
4124   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4125   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4126   PetscValidPointer(cells,3);
4127   if (dm->ops->locatepoints) {
4128     ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr);
4129   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM");
4130   PetscFunctionReturn(0);
4131 }
4132 
4133 #undef __FUNCT__
4134 #define __FUNCT__ "DMGetOutputDM"
4135 /*@
4136   DMGetOutputDM - Retrieve the DM associated with the layout for output
4137 
4138   Input Parameter:
4139 . dm - The original DM
4140 
4141   Output Parameter:
4142 . odm - The DM which provides the layout for output
4143 
4144   Level: intermediate
4145 
4146 .seealso: VecView(), DMGetDefaultGlobalSection()
4147 @*/
4148 PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
4149 {
4150   PetscSection   section;
4151   PetscBool      hasConstraints;
4152   PetscErrorCode ierr;
4153 
4154   PetscFunctionBegin;
4155   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4156   PetscValidPointer(odm,2);
4157   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
4158   ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr);
4159   if (!hasConstraints) {
4160     *odm = dm;
4161     PetscFunctionReturn(0);
4162   }
4163   if (!dm->dmBC) {
4164     PetscSection newSection, gsection;
4165     PetscSF      sf;
4166 
4167     ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr);
4168     ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr);
4169     ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr);
4170     ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr);
4171     ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr);
4172     ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, &gsection);CHKERRQ(ierr);
4173     ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr);
4174     ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr);
4175   }
4176   *odm = dm->dmBC;
4177   PetscFunctionReturn(0);
4178 }
4179 
4180 #undef __FUNCT__
4181 #define __FUNCT__ "DMGetOutputSequenceNumber"
4182 /*@
4183   DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
4184 
4185   Input Parameter:
4186 . dm - The original DM
4187 
4188   Output Parameters:
4189 + num - The output sequence number
4190 - val - The output sequence value
4191 
4192   Level: intermediate
4193 
4194   Note: This is intended for output that should appear in sequence, for instance
4195   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
4196 
4197 .seealso: VecView()
4198 @*/
4199 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
4200 {
4201   PetscFunctionBegin;
4202   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4203   if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;}
4204   if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;}
4205   PetscFunctionReturn(0);
4206 }
4207 
4208 #undef __FUNCT__
4209 #define __FUNCT__ "DMSetOutputSequenceNumber"
4210 /*@
4211   DMSetOutputSequenceNumber - Set the sequence number/value for output
4212 
4213   Input Parameters:
4214 + dm - The original DM
4215 . num - The output sequence number
4216 - val - The output sequence value
4217 
4218   Level: intermediate
4219 
4220   Note: This is intended for output that should appear in sequence, for instance
4221   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
4222 
4223 .seealso: VecView()
4224 @*/
4225 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
4226 {
4227   PetscFunctionBegin;
4228   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4229   dm->outputSequenceNum = num;
4230   dm->outputSequenceVal = val;
4231   PetscFunctionReturn(0);
4232 }
4233 
4234 #undef __FUNCT__
4235 #define __FUNCT__ "DMOutputSequenceLoad"
4236 /*@C
4237   DMOutputSequenceLoad - Retrieve the sequence value from a Viewer
4238 
4239   Input Parameters:
4240 + dm   - The original DM
4241 . name - The sequence name
4242 - num  - The output sequence number
4243 
4244   Output Parameter:
4245 . val  - The output sequence value
4246 
4247   Level: intermediate
4248 
4249   Note: This is intended for output that should appear in sequence, for instance
4250   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
4251 
4252 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView()
4253 @*/
4254 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
4255 {
4256   PetscBool      ishdf5;
4257   PetscErrorCode ierr;
4258 
4259   PetscFunctionBegin;
4260   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4261   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4262   PetscValidPointer(val,4);
4263   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
4264   if (ishdf5) {
4265 #if defined(PETSC_HAVE_HDF5)
4266     PetscScalar value;
4267 
4268     ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr);
4269     *val = PetscRealPart(value);
4270 #endif
4271   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
4272   PetscFunctionReturn(0);
4273 }
4274