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