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