xref: /petsc/src/dm/interface/dm.c (revision 0873808bba451bee251b952ef9c913fc3dcb5ce2)
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 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds.");
2002   PetscFunctionReturn(0);
2003 }
2004 
2005 #undef __FUNCT__
2006 #define __FUNCT__ "DMComputeInitialGuess"
2007 /*@
2008     DMComputeInitialGuess - computes an initial guess vector entries for the KSP solvers
2009 
2010     Collective on DM
2011 
2012     Input Parameter:
2013 +   dm - the DM object to destroy
2014 -   x - the vector to hold the initial guess values
2015 
2016     Level: developer
2017 
2018 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetRhs(), DMSetMat()
2019 
2020 @*/
2021 PetscErrorCode  DMComputeInitialGuess(DM dm,Vec x)
2022 {
2023   PetscErrorCode ierr;
2024   PetscFunctionBegin;
2025   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2026   if (!dm->ops->initialguess) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to provide function with DMSetInitialGuess()");
2027   ierr = (*dm->ops->initialguess)(dm,x);CHKERRQ(ierr);
2028   PetscFunctionReturn(0);
2029 }
2030 
2031 #undef __FUNCT__
2032 #define __FUNCT__ "DMHasInitialGuess"
2033 /*@
2034     DMHasInitialGuess - does the DM object have an initial guess function
2035 
2036     Not Collective
2037 
2038     Input Parameter:
2039 .   dm - the DM object to destroy
2040 
2041     Output Parameter:
2042 .   flg - PETSC_TRUE if function exists
2043 
2044     Level: developer
2045 
2046 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian()
2047 
2048 @*/
2049 PetscErrorCode  DMHasInitialGuess(DM dm,PetscBool  *flg)
2050 {
2051   PetscFunctionBegin;
2052   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2053   *flg =  (dm->ops->initialguess) ? PETSC_TRUE : PETSC_FALSE;
2054   PetscFunctionReturn(0);
2055 }
2056 
2057 #undef __FUNCT__
2058 #define __FUNCT__ "DMHasFunction"
2059 /*@
2060     DMHasFunction - does the DM object have a function
2061 
2062     Not Collective
2063 
2064     Input Parameter:
2065 .   dm - the DM object to destroy
2066 
2067     Output Parameter:
2068 .   flg - PETSC_TRUE if function exists
2069 
2070     Level: developer
2071 
2072 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian()
2073 
2074 @*/
2075 PetscErrorCode  DMHasFunction(DM dm,PetscBool  *flg)
2076 {
2077   PetscFunctionBegin;
2078   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2079   *flg =  (dm->ops->function) ? PETSC_TRUE : PETSC_FALSE;
2080   PetscFunctionReturn(0);
2081 }
2082 
2083 #undef __FUNCT__
2084 #define __FUNCT__ "DMHasJacobian"
2085 /*@
2086     DMHasJacobian - does the DM object have a matrix function
2087 
2088     Not Collective
2089 
2090     Input Parameter:
2091 .   dm - the DM object to destroy
2092 
2093     Output Parameter:
2094 .   flg - PETSC_TRUE if function exists
2095 
2096     Level: developer
2097 
2098 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian()
2099 
2100 @*/
2101 PetscErrorCode  DMHasJacobian(DM dm,PetscBool  *flg)
2102 {
2103   PetscFunctionBegin;
2104   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2105   *flg =  (dm->ops->jacobian) ? PETSC_TRUE : PETSC_FALSE;
2106   PetscFunctionReturn(0);
2107 }
2108 
2109 #undef  __FUNCT__
2110 #define __FUNCT__ "DMSetVec"
2111 /*@C
2112     DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear.
2113 
2114     Collective on DM
2115 
2116     Input Parameter:
2117 +   dm - the DM object
2118 -   x - location to compute residual and Jacobian, if PETSC_NULL is passed to those routines; will be PETSC_NULL for linear problems.
2119 
2120     Level: developer
2121 
2122 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetInitialGuess(),
2123          DMSetFunction(), DMSetJacobian(), DMSetVariableBounds()
2124 
2125 @*/
2126 PetscErrorCode  DMSetVec(DM dm,Vec x)
2127 {
2128   PetscErrorCode ierr;
2129   PetscFunctionBegin;
2130   if (x) {
2131     if (!dm->x) {
2132       ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr);
2133     }
2134     ierr = VecCopy(x,dm->x);CHKERRQ(ierr);
2135   }
2136   else if(dm->x) {
2137     ierr = VecDestroy(&dm->x);  CHKERRQ(ierr);
2138   }
2139   PetscFunctionReturn(0);
2140 }
2141 
2142 
2143 #undef __FUNCT__
2144 #define __FUNCT__ "DMComputeFunction"
2145 /*@
2146     DMComputeFunction - computes the right hand side vector entries for the KSP solver or nonlinear function for SNES
2147 
2148     Collective on DM
2149 
2150     Input Parameter:
2151 +   dm - the DM object to destroy
2152 .   x - the location where the function is evaluationed, may be ignored for linear problems
2153 -   b - the vector to hold the right hand side entries
2154 
2155     Level: developer
2156 
2157 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetInitialGuess(),
2158          DMSetJacobian()
2159 
2160 @*/
2161 PetscErrorCode  DMComputeFunction(DM dm,Vec x,Vec b)
2162 {
2163   PetscErrorCode ierr;
2164   PetscFunctionBegin;
2165   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2166   if (!dm->ops->function) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to provide function with DMSetFunction()");
2167   PetscStackPush("DM user function");
2168   ierr = (*dm->ops->function)(dm,x,b);CHKERRQ(ierr);
2169   PetscStackPop;
2170   PetscFunctionReturn(0);
2171 }
2172 
2173 
2174 
2175 #undef __FUNCT__
2176 #define __FUNCT__ "DMComputeJacobian"
2177 /*@
2178     DMComputeJacobian - compute the matrix entries for the solver
2179 
2180     Collective on DM
2181 
2182     Input Parameter:
2183 +   dm - the DM object
2184 .   x - location to compute Jacobian at; will be PETSC_NULL for linear problems, for nonlinear problems if not provided then pulled from DM
2185 .   A - matrix that defines the operator for the linear solve
2186 -   B - the matrix used to construct the preconditioner
2187 
2188     Level: developer
2189 
2190 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetInitialGuess(),
2191          DMSetFunction()
2192 
2193 @*/
2194 PetscErrorCode  DMComputeJacobian(DM dm,Vec x,Mat A,Mat B,MatStructure *stflag)
2195 {
2196   PetscErrorCode ierr;
2197 
2198   PetscFunctionBegin;
2199   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2200   if (!dm->ops->jacobian) {
2201     ISColoring     coloring;
2202     MatFDColoring  fd;
2203     const MatType  mtype;
2204 
2205     ierr = PetscObjectGetType((PetscObject)B,&mtype);CHKERRQ(ierr);
2206     ierr = DMCreateColoring(dm,dm->coloringtype,mtype,&coloring);CHKERRQ(ierr);
2207     ierr = MatFDColoringCreate(B,coloring,&fd);CHKERRQ(ierr);
2208     ierr = ISColoringDestroy(&coloring);CHKERRQ(ierr);
2209     ierr = MatFDColoringSetFunction(fd,(PetscErrorCode (*)(void))dm->ops->functionj,dm);CHKERRQ(ierr);
2210     ierr = PetscObjectSetOptionsPrefix((PetscObject)fd,((PetscObject)dm)->prefix);CHKERRQ(ierr);
2211     ierr = MatFDColoringSetFromOptions(fd);CHKERRQ(ierr);
2212 
2213     dm->fd = fd;
2214     dm->ops->jacobian = DMComputeJacobianDefault;
2215 
2216     /* don't know why this is needed */
2217     ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr);
2218   }
2219   if (!x) x = dm->x;
2220   ierr = (*dm->ops->jacobian)(dm,x,A,B,stflag);CHKERRQ(ierr);
2221 
2222   /* if matrix depends on x; i.e. nonlinear problem, keep copy of input vector since needed by multigrid methods to generate coarse grid matrices */
2223   if (x) {
2224     if (!dm->x) {
2225       ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr);
2226     }
2227     ierr = VecCopy(x,dm->x);CHKERRQ(ierr);
2228   }
2229   if (A != B) {
2230     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2231     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2232   }
2233   PetscFunctionReturn(0);
2234 }
2235 
2236 
2237 PetscFList DMList                       = PETSC_NULL;
2238 PetscBool  DMRegisterAllCalled          = PETSC_FALSE;
2239 
2240 #undef __FUNCT__
2241 #define __FUNCT__ "DMSetType"
2242 /*@C
2243   DMSetType - Builds a DM, for a particular DM implementation.
2244 
2245   Collective on DM
2246 
2247   Input Parameters:
2248 + dm     - The DM object
2249 - method - The name of the DM type
2250 
2251   Options Database Key:
2252 . -dm_type <type> - Sets the DM type; use -help for a list of available types
2253 
2254   Notes:
2255   See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).
2256 
2257   Level: intermediate
2258 
2259 .keywords: DM, set, type
2260 .seealso: DMGetType(), DMCreate()
2261 @*/
2262 PetscErrorCode  DMSetType(DM dm, const DMType method)
2263 {
2264   PetscErrorCode (*r)(DM);
2265   PetscBool      match;
2266   PetscErrorCode ierr;
2267 
2268   PetscFunctionBegin;
2269   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
2270   ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr);
2271   if (match) PetscFunctionReturn(0);
2272 
2273   if (!DMRegisterAllCalled) {ierr = DMRegisterAll(PETSC_NULL);CHKERRQ(ierr);}
2274   ierr = PetscFListFind(DMList, ((PetscObject)dm)->comm, method,PETSC_TRUE,(void (**)(void)) &r);CHKERRQ(ierr);
2275   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
2276 
2277   if (dm->ops->destroy) {
2278     ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr);
2279     dm->ops->destroy = PETSC_NULL;
2280   }
2281   ierr = (*r)(dm);CHKERRQ(ierr);
2282   ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr);
2283   PetscFunctionReturn(0);
2284 }
2285 
2286 #undef __FUNCT__
2287 #define __FUNCT__ "DMGetType"
2288 /*@C
2289   DMGetType - Gets the DM type name (as a string) from the DM.
2290 
2291   Not Collective
2292 
2293   Input Parameter:
2294 . dm  - The DM
2295 
2296   Output Parameter:
2297 . type - The DM type name
2298 
2299   Level: intermediate
2300 
2301 .keywords: DM, get, type, name
2302 .seealso: DMSetType(), DMCreate()
2303 @*/
2304 PetscErrorCode  DMGetType(DM dm, const DMType *type)
2305 {
2306   PetscErrorCode ierr;
2307 
2308   PetscFunctionBegin;
2309   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
2310   PetscValidCharPointer(type,2);
2311   if (!DMRegisterAllCalled) {
2312     ierr = DMRegisterAll(PETSC_NULL);CHKERRQ(ierr);
2313   }
2314   *type = ((PetscObject)dm)->type_name;
2315   PetscFunctionReturn(0);
2316 }
2317 
2318 #undef __FUNCT__
2319 #define __FUNCT__ "DMConvert"
2320 /*@C
2321   DMConvert - Converts a DM to another DM, either of the same or different type.
2322 
2323   Collective on DM
2324 
2325   Input Parameters:
2326 + dm - the DM
2327 - newtype - new DM type (use "same" for the same type)
2328 
2329   Output Parameter:
2330 . M - pointer to new DM
2331 
2332   Notes:
2333   Cannot be used to convert a sequential DM to parallel or parallel to sequential,
2334   the MPI communicator of the generated DM is always the same as the communicator
2335   of the input DM.
2336 
2337   Level: intermediate
2338 
2339 .seealso: DMCreate()
2340 @*/
2341 PetscErrorCode DMConvert(DM dm, const DMType newtype, DM *M)
2342 {
2343   DM             B;
2344   char           convname[256];
2345   PetscBool      sametype, issame;
2346   PetscErrorCode ierr;
2347 
2348   PetscFunctionBegin;
2349   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2350   PetscValidType(dm,1);
2351   PetscValidPointer(M,3);
2352   ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr);
2353   ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr);
2354   {
2355     PetscErrorCode (*conv)(DM, const DMType, DM *) = PETSC_NULL;
2356 
2357     /*
2358        Order of precedence:
2359        1) See if a specialized converter is known to the current DM.
2360        2) See if a specialized converter is known to the desired DM class.
2361        3) See if a good general converter is registered for the desired class
2362        4) See if a good general converter is known for the current matrix.
2363        5) Use a really basic converter.
2364     */
2365 
2366     /* 1) See if a specialized converter is known to the current DM and the desired class */
2367     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
2368     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
2369     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
2370     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
2371     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
2372     ierr = PetscObjectQueryFunction((PetscObject)dm,convname,(void (**)(void))&conv);CHKERRQ(ierr);
2373     if (conv) goto foundconv;
2374 
2375     /* 2)  See if a specialized converter is known to the desired DM class. */
2376     ierr = DMCreate(((PetscObject) dm)->comm, &B);CHKERRQ(ierr);
2377     ierr = DMSetType(B, newtype);CHKERRQ(ierr);
2378     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
2379     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
2380     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
2381     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
2382     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
2383     ierr = PetscObjectQueryFunction((PetscObject)B,convname,(void (**)(void))&conv);CHKERRQ(ierr);
2384     if (conv) {
2385       ierr = DMDestroy(&B);CHKERRQ(ierr);
2386       goto foundconv;
2387     }
2388 
2389 #if 0
2390     /* 3) See if a good general converter is registered for the desired class */
2391     conv = B->ops->convertfrom;
2392     ierr = DMDestroy(&B);CHKERRQ(ierr);
2393     if (conv) goto foundconv;
2394 
2395     /* 4) See if a good general converter is known for the current matrix */
2396     if (dm->ops->convert) {
2397       conv = dm->ops->convert;
2398     }
2399     if (conv) goto foundconv;
2400 #endif
2401 
2402     /* 5) Use a really basic converter. */
2403     SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);
2404 
2405     foundconv:
2406     ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
2407     ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr);
2408     ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
2409   }
2410   ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr);
2411   PetscFunctionReturn(0);
2412 }
2413 
2414 /*--------------------------------------------------------------------------------------------------------------------*/
2415 
2416 #undef __FUNCT__
2417 #define __FUNCT__ "DMRegister"
2418 /*@C
2419   DMRegister - See DMRegisterDynamic()
2420 
2421   Level: advanced
2422 @*/
2423 PetscErrorCode  DMRegister(const char sname[], const char path[], const char name[], PetscErrorCode (*function)(DM))
2424 {
2425   char fullname[PETSC_MAX_PATH_LEN];
2426   PetscErrorCode ierr;
2427 
2428   PetscFunctionBegin;
2429   ierr = PetscStrcpy(fullname, path);CHKERRQ(ierr);
2430   ierr = PetscStrcat(fullname, ":");CHKERRQ(ierr);
2431   ierr = PetscStrcat(fullname, name);CHKERRQ(ierr);
2432   ierr = PetscFListAdd(&DMList, sname, fullname, (void (*)(void)) function);CHKERRQ(ierr);
2433   PetscFunctionReturn(0);
2434 }
2435 
2436 
2437 /*--------------------------------------------------------------------------------------------------------------------*/
2438 #undef __FUNCT__
2439 #define __FUNCT__ "DMRegisterDestroy"
2440 /*@C
2441    DMRegisterDestroy - Frees the list of DM methods that were registered by DMRegister()/DMRegisterDynamic().
2442 
2443    Not Collective
2444 
2445    Level: advanced
2446 
2447 .keywords: DM, register, destroy
2448 .seealso: DMRegister(), DMRegisterAll(), DMRegisterDynamic()
2449 @*/
2450 PetscErrorCode  DMRegisterDestroy(void)
2451 {
2452   PetscErrorCode ierr;
2453 
2454   PetscFunctionBegin;
2455   ierr = PetscFListDestroy(&DMList);CHKERRQ(ierr);
2456   DMRegisterAllCalled = PETSC_FALSE;
2457   PetscFunctionReturn(0);
2458 }
2459 
2460 #if defined(PETSC_HAVE_MATLAB_ENGINE)
2461 #include <mex.h>
2462 
2463 typedef struct {char *funcname; char *jacname; mxArray *ctx;} DMMatlabContext;
2464 
2465 #undef __FUNCT__
2466 #define __FUNCT__ "DMComputeFunction_Matlab"
2467 /*
2468    DMComputeFunction_Matlab - Calls the function that has been set with
2469                          DMSetFunctionMatlab().
2470 
2471    For linear problems x is null
2472 
2473 .seealso: DMSetFunction(), DMGetFunction()
2474 */
2475 PetscErrorCode  DMComputeFunction_Matlab(DM dm,Vec x,Vec y)
2476 {
2477   PetscErrorCode    ierr;
2478   DMMatlabContext   *sctx;
2479   int               nlhs = 1,nrhs = 4;
2480   mxArray	    *plhs[1],*prhs[4];
2481   long long int     lx = 0,ly = 0,ls = 0;
2482 
2483   PetscFunctionBegin;
2484   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2485   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2486   PetscCheckSameComm(dm,1,y,3);
2487 
2488   /* call Matlab function in ctx with arguments x and y */
2489   ierr = DMGetApplicationContext(dm,&sctx);CHKERRQ(ierr);
2490   ierr = PetscMemcpy(&ls,&dm,sizeof(dm));CHKERRQ(ierr);
2491   ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr);
2492   ierr = PetscMemcpy(&ly,&y,sizeof(y));CHKERRQ(ierr);
2493   prhs[0] =  mxCreateDoubleScalar((double)ls);
2494   prhs[1] =  mxCreateDoubleScalar((double)lx);
2495   prhs[2] =  mxCreateDoubleScalar((double)ly);
2496   prhs[3] =  mxCreateString(sctx->funcname);
2497   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscDMComputeFunctionInternal");CHKERRQ(ierr);
2498   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
2499   mxDestroyArray(prhs[0]);
2500   mxDestroyArray(prhs[1]);
2501   mxDestroyArray(prhs[2]);
2502   mxDestroyArray(prhs[3]);
2503   mxDestroyArray(plhs[0]);
2504   PetscFunctionReturn(0);
2505 }
2506 
2507 
2508 #undef __FUNCT__
2509 #define __FUNCT__ "DMSetFunctionMatlab"
2510 /*
2511    DMSetFunctionMatlab - Sets the function evaluation routine
2512 
2513 */
2514 PetscErrorCode  DMSetFunctionMatlab(DM dm,const char *func)
2515 {
2516   PetscErrorCode    ierr;
2517   DMMatlabContext   *sctx;
2518 
2519   PetscFunctionBegin;
2520   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2521   /* currently sctx is memory bleed */
2522   ierr = DMGetApplicationContext(dm,&sctx);CHKERRQ(ierr);
2523   if (!sctx) {
2524     ierr = PetscMalloc(sizeof(DMMatlabContext),&sctx);CHKERRQ(ierr);
2525   }
2526   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
2527   ierr = DMSetApplicationContext(dm,sctx);CHKERRQ(ierr);
2528   ierr = DMSetFunction(dm,DMComputeFunction_Matlab);CHKERRQ(ierr);
2529   PetscFunctionReturn(0);
2530 }
2531 
2532 #undef __FUNCT__
2533 #define __FUNCT__ "DMComputeJacobian_Matlab"
2534 /*
2535    DMComputeJacobian_Matlab - Calls the function that has been set with
2536                          DMSetJacobianMatlab().
2537 
2538    For linear problems x is null
2539 
2540 .seealso: DMSetFunction(), DMGetFunction()
2541 */
2542 PetscErrorCode  DMComputeJacobian_Matlab(DM dm,Vec x,Mat A,Mat B,MatStructure *str)
2543 {
2544   PetscErrorCode    ierr;
2545   DMMatlabContext   *sctx;
2546   int               nlhs = 2,nrhs = 5;
2547   mxArray	    *plhs[2],*prhs[5];
2548   long long int     lx = 0,lA = 0,lB = 0,ls = 0;
2549 
2550   PetscFunctionBegin;
2551   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2552   PetscValidHeaderSpecific(A,MAT_CLASSID,3);
2553 
2554   /* call MATLAB function in ctx with arguments x, A, and B */
2555   ierr = DMGetApplicationContext(dm,&sctx);CHKERRQ(ierr);
2556   ierr = PetscMemcpy(&ls,&dm,sizeof(dm));CHKERRQ(ierr);
2557   ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr);
2558   ierr = PetscMemcpy(&lA,&A,sizeof(A));CHKERRQ(ierr);
2559   ierr = PetscMemcpy(&lB,&B,sizeof(B));CHKERRQ(ierr);
2560   prhs[0] =  mxCreateDoubleScalar((double)ls);
2561   prhs[1] =  mxCreateDoubleScalar((double)lx);
2562   prhs[2] =  mxCreateDoubleScalar((double)lA);
2563   prhs[3] =  mxCreateDoubleScalar((double)lB);
2564   prhs[4] =  mxCreateString(sctx->jacname);
2565   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscDMComputeJacobianInternal");CHKERRQ(ierr);
2566   *str    =  (MatStructure) mxGetScalar(plhs[0]);
2567   ierr    =  (PetscInt) mxGetScalar(plhs[1]);CHKERRQ(ierr);
2568   mxDestroyArray(prhs[0]);
2569   mxDestroyArray(prhs[1]);
2570   mxDestroyArray(prhs[2]);
2571   mxDestroyArray(prhs[3]);
2572   mxDestroyArray(prhs[4]);
2573   mxDestroyArray(plhs[0]);
2574   mxDestroyArray(plhs[1]);
2575   PetscFunctionReturn(0);
2576 }
2577 
2578 
2579 #undef __FUNCT__
2580 #define __FUNCT__ "DMSetJacobianMatlab"
2581 /*
2582    DMSetJacobianMatlab - Sets the Jacobian function evaluation routine
2583 
2584 */
2585 PetscErrorCode  DMSetJacobianMatlab(DM dm,const char *func)
2586 {
2587   PetscErrorCode    ierr;
2588   DMMatlabContext   *sctx;
2589 
2590   PetscFunctionBegin;
2591   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2592   /* currently sctx is memory bleed */
2593   ierr = DMGetApplicationContext(dm,&sctx);CHKERRQ(ierr);
2594   if (!sctx) {
2595     ierr = PetscMalloc(sizeof(DMMatlabContext),&sctx);CHKERRQ(ierr);
2596   }
2597   ierr = PetscStrallocpy(func,&sctx->jacname);CHKERRQ(ierr);
2598   ierr = DMSetApplicationContext(dm,sctx);CHKERRQ(ierr);
2599   ierr = DMSetJacobian(dm,DMComputeJacobian_Matlab);CHKERRQ(ierr);
2600   PetscFunctionReturn(0);
2601 }
2602 #endif
2603 
2604 #undef __FUNCT__
2605 #define __FUNCT__ "DMLoad"
2606 /*@C
2607   DMLoad - Loads a DM that has been stored in binary or HDF5 format
2608   with DMView().
2609 
2610   Collective on PetscViewer
2611 
2612   Input Parameters:
2613 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
2614            some related function before a call to DMLoad().
2615 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
2616            HDF5 file viewer, obtained from PetscViewerHDF5Open()
2617 
2618    Level: intermediate
2619 
2620   Notes:
2621   Defaults to the DM DA.
2622 
2623   Notes for advanced users:
2624   Most users should not need to know the details of the binary storage
2625   format, since DMLoad() and DMView() completely hide these details.
2626   But for anyone who's interested, the standard binary matrix storage
2627   format is
2628 .vb
2629      has not yet been determined
2630 .ve
2631 
2632    In addition, PETSc automatically does the byte swapping for
2633 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
2634 linux, Windows and the paragon; thus if you write your own binary
2635 read/write routines you have to swap the bytes; see PetscBinaryRead()
2636 and PetscBinaryWrite() to see how this may be done.
2637 
2638   Concepts: vector^loading from file
2639 
2640 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad()
2641 @*/
2642 PetscErrorCode  DMLoad(DM newdm, PetscViewer viewer)
2643 {
2644   PetscErrorCode ierr;
2645 
2646   PetscFunctionBegin;
2647   PetscValidHeaderSpecific(newdm,DM_CLASSID,1);
2648   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
2649 
2650   if (!((PetscObject)newdm)->type_name) {
2651     ierr = DMSetType(newdm, DMDA);CHKERRQ(ierr);
2652   }
2653   ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);
2654   PetscFunctionReturn(0);
2655 }
2656 
2657 /******************************** FEM Support **********************************/
2658 
2659 #undef __FUNCT__
2660 #define __FUNCT__ "DMPrintCellVector"
2661 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) {
2662   PetscInt       f;
2663   PetscErrorCode ierr;
2664 
2665   PetscFunctionBegin;
2666   ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
2667   for(f = 0; f < len; ++f) {
2668     ierr = PetscPrintf(PETSC_COMM_SELF, "  | %G |\n", PetscRealPart(x[f]));CHKERRQ(ierr);
2669   }
2670   PetscFunctionReturn(0);
2671 }
2672 
2673 #undef __FUNCT__
2674 #define __FUNCT__ "DMPrintCellMatrix"
2675 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) {
2676   PetscInt       f, g;
2677   PetscErrorCode ierr;
2678 
2679   PetscFunctionBegin;
2680   ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
2681   for(f = 0; f < rows; ++f) {
2682     ierr = PetscPrintf(PETSC_COMM_SELF, "  |");CHKERRQ(ierr);
2683     for(g = 0; g < cols; ++g) {
2684       ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5G", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr);
2685     }
2686     ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr);
2687   }
2688   PetscFunctionReturn(0);
2689 }
2690 
2691 #undef __FUNCT__
2692 #define __FUNCT__ "DMGetLocalFunction"
2693 /*@C
2694   DMGetLocalFunction - Get the local residual function from this DM
2695 
2696   Not collective
2697 
2698   Input Parameter:
2699 . dm - The DM
2700 
2701   Output Parameter:
2702 . lf - The local residual function
2703 
2704    Calling sequence of lf:
2705 $    lf (SNES snes, Vec x, Vec f, void *ctx);
2706 
2707 +  snes - the SNES context
2708 .  x - local vector with the state at which to evaluate residual
2709 .  f - local vector to put residual in
2710 -  ctx - optional user-defined function context
2711 
2712   Level: intermediate
2713 
2714 .seealso DMSetLocalFunction(), DMGetLocalJacobian(), DMSetLocalJacobian()
2715 @*/
2716 PetscErrorCode DMGetLocalFunction(DM dm, PetscErrorCode (**lf)(DM, Vec, Vec, void *))
2717 {
2718   PetscFunctionBegin;
2719   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2720   if (lf) *lf = dm->lf;
2721   PetscFunctionReturn(0);
2722 }
2723 
2724 #undef __FUNCT__
2725 #define __FUNCT__ "DMSetLocalFunction"
2726 /*@C
2727   DMSetLocalFunction - Set the local residual function from this DM
2728 
2729   Not collective
2730 
2731   Input Parameters:
2732 + dm - The DM
2733 - lf - The local residual function
2734 
2735    Calling sequence of lf:
2736 $    lf (SNES snes, Vec x, Vec f, void *ctx);
2737 
2738 +  snes - the SNES context
2739 .  x - local vector with the state at which to evaluate residual
2740 .  f - local vector to put residual in
2741 -  ctx - optional user-defined function context
2742 
2743   Level: intermediate
2744 
2745 .seealso DMGetLocalFunction(), DMGetLocalJacobian(), DMSetLocalJacobian()
2746 @*/
2747 PetscErrorCode DMSetLocalFunction(DM dm, PetscErrorCode (*lf)(DM, Vec, Vec, void *))
2748 {
2749   PetscFunctionBegin;
2750   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2751   dm->lf = lf;
2752   PetscFunctionReturn(0);
2753 }
2754 
2755 #undef __FUNCT__
2756 #define __FUNCT__ "DMGetLocalJacobian"
2757 /*@C
2758   DMGetLocalJacobian - Get the local Jacobian function from this DM
2759 
2760   Not collective
2761 
2762   Input Parameter:
2763 . dm - The DM
2764 
2765   Output Parameter:
2766 . lj - The local Jacobian function
2767 
2768    Calling sequence of lj:
2769 $    lj (SNES snes, Vec x, Mat J, Mat M, void *ctx);
2770 
2771 +  snes - the SNES context
2772 .  x - local vector with the state at which to evaluate residual
2773 .  J - matrix to put Jacobian in
2774 .  M - matrix to use for defining Jacobian preconditioner
2775 -  ctx - optional user-defined function context
2776 
2777   Level: intermediate
2778 
2779 .seealso DMSetLocalJacobian(), DMGetLocalFunction(), DMSetLocalFunction()
2780 @*/
2781 PetscErrorCode DMGetLocalJacobian(DM dm, PetscErrorCode (**lj)(DM, Vec, Mat, Mat, void *))
2782 {
2783   PetscFunctionBegin;
2784   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2785   if (lj) *lj = dm->lj;
2786   PetscFunctionReturn(0);
2787 }
2788 
2789 #undef __FUNCT__
2790 #define __FUNCT__ "DMSetLocalJacobian"
2791 /*@C
2792   DMSetLocalJacobian - Set the local Jacobian function from this DM
2793 
2794   Not collective
2795 
2796   Input Parameters:
2797 + dm - The DM
2798 - lj - The local Jacobian function
2799 
2800    Calling sequence of lj:
2801 $    lj (SNES snes, Vec x, Mat J, Mat M, void *ctx);
2802 
2803 +  snes - the SNES context
2804 .  x - local vector with the state at which to evaluate residual
2805 .  J - matrix to put Jacobian in
2806 .  M - matrix to use for defining Jacobian preconditioner
2807 -  ctx - optional user-defined function context
2808 
2809   Level: intermediate
2810 
2811 .seealso DMGetLocalJacobian(), DMGetLocalFunction(), DMSetLocalFunction()
2812 @*/
2813 PetscErrorCode DMSetLocalJacobian(DM dm, PetscErrorCode (*lj)(DM, Vec, Mat,  Mat, void *))
2814 {
2815   PetscFunctionBegin;
2816   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2817   dm->lj = lj;
2818   PetscFunctionReturn(0);
2819 }
2820 
2821 #undef __FUNCT__
2822 #define __FUNCT__ "DMGetDefaultSection"
2823 /*@
2824   DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM.
2825 
2826   Input Parameter:
2827 . dm - The DM
2828 
2829   Output Parameter:
2830 . section - The PetscSection
2831 
2832   Level: intermediate
2833 
2834   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
2835 
2836 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
2837 @*/
2838 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section) {
2839   PetscFunctionBegin;
2840   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2841   PetscValidPointer(section, 2);
2842   *section = dm->defaultSection;
2843   PetscFunctionReturn(0);
2844 }
2845 
2846 #undef __FUNCT__
2847 #define __FUNCT__ "DMSetDefaultSection"
2848 /*@
2849   DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM.
2850 
2851   Input Parameters:
2852 + dm - The DM
2853 - section - The PetscSection
2854 
2855   Level: intermediate
2856 
2857   Note: Any existing Section will be destroyed
2858 
2859 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
2860 @*/
2861 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section) {
2862   PetscErrorCode ierr;
2863 
2864   PetscFunctionBegin;
2865   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2866   ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr);
2867   ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr);
2868   dm->defaultSection = section;
2869   PetscFunctionReturn(0);
2870 }
2871 
2872 #undef __FUNCT__
2873 #define __FUNCT__ "DMGetDefaultGlobalSection"
2874 /*@
2875   DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM.
2876 
2877   Input Parameter:
2878 . dm - The DM
2879 
2880   Output Parameter:
2881 . section - The PetscSection
2882 
2883   Level: intermediate
2884 
2885   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
2886 
2887 .seealso: DMSetDefaultSection(), DMGetDefaultSection()
2888 @*/
2889 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) {
2890   PetscErrorCode ierr;
2891 
2892   PetscFunctionBegin;
2893   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2894   PetscValidPointer(section, 2);
2895   if (!dm->defaultGlobalSection) {
2896     ierr = PetscSectionCreateGlobalSection(dm->defaultSection, dm->sf, &dm->defaultGlobalSection);CHKERRQ(ierr);
2897   }
2898   *section = dm->defaultGlobalSection;
2899   PetscFunctionReturn(0);
2900 }
2901 
2902 #undef __FUNCT__
2903 #define __FUNCT__ "DMGetDefaultSF"
2904 /*@
2905   DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set,
2906   it is created from the default PetscSection layouts in the DM.
2907 
2908   Input Parameter:
2909 . dm - The DM
2910 
2911   Output Parameter:
2912 . sf - The PetscSF
2913 
2914   Level: intermediate
2915 
2916   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
2917 
2918 .seealso: DMSetDefaultSF(), DMCreateDefaultSF()
2919 @*/
2920 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) {
2921   PetscInt       nroots;
2922   PetscErrorCode ierr;
2923 
2924   PetscFunctionBegin;
2925   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2926   PetscValidPointer(sf, 2);
2927   ierr = PetscSFGetGraph(dm->defaultSF, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr);
2928   if (nroots < 0) {
2929     PetscSection section, gSection;
2930 
2931     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
2932     if (section) {
2933       ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr);
2934       ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr);
2935     } else {
2936       *sf = PETSC_NULL;
2937       PetscFunctionReturn(0);
2938     }
2939   }
2940   *sf = dm->defaultSF;
2941   PetscFunctionReturn(0);
2942 }
2943 
2944 #undef __FUNCT__
2945 #define __FUNCT__ "DMSetDefaultSF"
2946 /*@
2947   DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM
2948 
2949   Input Parameters:
2950 + dm - The DM
2951 - sf - The PetscSF
2952 
2953   Level: intermediate
2954 
2955   Note: Any previous SF is destroyed
2956 
2957 .seealso: DMGetDefaultSF(), DMCreateDefaultSF()
2958 @*/
2959 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) {
2960   PetscErrorCode ierr;
2961 
2962   PetscFunctionBegin;
2963   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2964   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
2965   ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr);
2966   dm->defaultSF = sf;
2967   PetscFunctionReturn(0);
2968 }
2969 
2970 #undef __FUNCT__
2971 #define __FUNCT__ "DMCreateDefaultSF"
2972 /*@C
2973   DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections
2974   describing the data layout.
2975 
2976   Input Parameters:
2977 + dm - The DM
2978 . localSection - PetscSection describing the local data layout
2979 - globalSection - PetscSection describing the global data layout
2980 
2981   Level: intermediate
2982 
2983 .seealso: DMGetDefaultSF(), DMSetDefaultSF()
2984 @*/
2985 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection)
2986 {
2987   MPI_Comm        comm = ((PetscObject) dm)->comm;
2988   PetscLayout     layout;
2989   const PetscInt *ranges;
2990   PetscInt       *local;
2991   PetscSFNode    *remote;
2992   PetscInt        pStart, pEnd, p, nroots, nleaves, l;
2993   PetscMPIInt     size, rank;
2994   PetscErrorCode  ierr;
2995 
2996   PetscFunctionBegin;
2997   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2998   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
2999   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3000   ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr);
3001   ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr);
3002   ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
3003   ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
3004   ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr);
3005   ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
3006   ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
3007   for(p = pStart, nleaves = 0; p < pEnd; ++p) {
3008     PetscInt dof, cdof;
3009 
3010     ierr = PetscSectionGetDof(globalSection, p, &dof);CHKERRQ(ierr);
3011     ierr = PetscSectionGetConstraintDof(globalSection, p, &cdof);CHKERRQ(ierr);
3012     nleaves += dof < 0 ? -(dof+1)-cdof : dof-cdof;
3013   }
3014   ierr = PetscMalloc(nleaves * sizeof(PetscInt), &local);CHKERRQ(ierr);
3015   ierr = PetscMalloc(nleaves * sizeof(PetscSFNode), &remote);CHKERRQ(ierr);
3016   for(p = pStart, l = 0; p < pEnd; ++p) {
3017     PetscInt *cind;
3018     PetscInt  dof, gdof, cdof, dim, off, goff, d, c;
3019 
3020     ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr);
3021     ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr);
3022     ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr);
3023     ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr);
3024     ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3025     ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr);
3026     dim  = dof-cdof;
3027     for(d = 0, c = 0; d < dof; ++d) {
3028       if ((c < cdof) && (cind[c] == d)) {++c; continue;}
3029       local[l+d-c] = off+d;
3030     }
3031     if (gdof < 0) {
3032       for(d = 0; d < dim; ++d, ++l) {
3033         PetscInt offset = -(goff+1) + d, r;
3034 
3035         for(r = 0; r < size; ++r) {
3036           if ((offset >= ranges[r]) && (offset < ranges[r+1])) break;
3037         }
3038         remote[l].rank  = r;
3039         remote[l].index = offset - ranges[r];
3040       }
3041     } else {
3042       for(d = 0; d < dim; ++d, ++l) {
3043         remote[l].rank  = rank;
3044         remote[l].index = goff+d - ranges[rank];
3045       }
3046     }
3047   }
3048   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
3049   ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr);
3050   PetscFunctionReturn(0);
3051 }
3052