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