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