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