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