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