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