xref: /petsc/src/dm/interface/dm.c (revision d4a378da529a33c9fd3485de6780ea57674d47bd)
1 
2 #include <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 vector object. The type can then be set with DMetType().
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 = DMInitializePackage(PETSC_NULL);CHKERRQ(ierr);
37 #endif
38 
39   ierr = PetscHeaderCreate(v, _p_DM, struct _DMOps, DM_CLASSID, -1, "DM", comm, DMDestroy, DMView);CHKERRQ(ierr);
40   ierr = PetscMemzero(v->ops, sizeof(struct _DMOps));CHKERRQ(ierr);
41 
42   v->ltogmap      = PETSC_NULL;
43   v->ltogmapb     = PETSC_NULL;
44   v->bs           = 1;
45 
46   *dm = v;
47   PetscFunctionReturn(0);
48 }
49 
50 
51 #undef __FUNCT__
52 #define __FUNCT__ "DMSetVecType"
53 /*@C
54        DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
55 
56    Logically Collective on DMDA
57 
58    Input Parameter:
59 +  da - initial distributed array
60 .  ctype - the vector type, currently either VECSTANDARD or VECCUSP
61 
62    Options Database:
63 .   -da_vec_type ctype
64 
65    Level: intermediate
66 
67 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType, VecType
68 @*/
69 PetscErrorCode  DMSetVecType(DM da,const VecType ctype)
70 {
71   PetscErrorCode ierr;
72 
73   PetscFunctionBegin;
74   PetscValidHeaderSpecific(da,DM_CLASSID,1);
75   ierr = PetscFree(da->vectype);CHKERRQ(ierr);
76   ierr = PetscStrallocpy(ctype,&da->vectype);CHKERRQ(ierr);
77   PetscFunctionReturn(0);
78 }
79 
80 #undef __FUNCT__
81 #define __FUNCT__ "DMSetOptionsPrefix"
82 /*@C
83    DMSetOptionsPrefix - Sets the prefix used for searching for all
84    DMDA options in the database.
85 
86    Logically Collective on DMDA
87 
88    Input Parameter:
89 +  da - the DMDA context
90 -  prefix - the prefix to prepend to all option names
91 
92    Notes:
93    A hyphen (-) must NOT be given at the beginning of the prefix name.
94    The first character of all runtime options is AUTOMATICALLY the hyphen.
95 
96    Level: advanced
97 
98 .keywords: DMDA, set, options, prefix, database
99 
100 .seealso: DMSetFromOptions()
101 @*/
102 PetscErrorCode  DMSetOptionsPrefix(DM dm,const char prefix[])
103 {
104   PetscErrorCode ierr;
105 
106   PetscFunctionBegin;
107   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
108   ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr);
109   PetscFunctionReturn(0);
110 }
111 
112 #undef __FUNCT__
113 #define __FUNCT__ "DMDestroy"
114 /*@
115     DMDestroy - Destroys a vector packer or DMDA.
116 
117     Collective on DM
118 
119     Input Parameter:
120 .   dm - the DM object to destroy
121 
122     Level: developer
123 
124 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()
125 
126 @*/
127 PetscErrorCode  DMDestroy(DM *dm)
128 {
129   PetscInt       i, cnt = 0;
130   PetscErrorCode ierr;
131 
132   PetscFunctionBegin;
133   if (!*dm) PetscFunctionReturn(0);
134   PetscValidHeaderSpecific((*dm),DM_CLASSID,1);
135   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
136     if ((*dm)->localin[i])  {cnt++;}
137     if ((*dm)->globalin[i]) {cnt++;}
138   }
139 
140   if (--((PetscObject)(*dm))->refct - cnt > 0) {*dm = 0; PetscFunctionReturn(0);}
141   /*
142      Need this test because the dm references the vectors that
143      reference the dm, so destroying the dm calls destroy on the
144      vectors that cause another destroy on the dm
145   */
146   if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0);
147   ((PetscObject) (*dm))->refct = 0;
148   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
149     if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()");
150     ierr = VecDestroy(&(*dm)->localin[i]);CHKERRQ(ierr);
151   }
152   ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr);
153   ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr);
154   ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmapb);CHKERRQ(ierr);
155   ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr);
156 
157   /* if memory was published with AMS then destroy it */
158   ierr = PetscObjectDepublish(*dm);CHKERRQ(ierr);
159 
160   ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr);
161   ierr = PetscFree((*dm)->data);CHKERRQ(ierr);
162   ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr);
163   PetscFunctionReturn(0);
164 }
165 
166 #undef __FUNCT__
167 #define __FUNCT__ "DMSetUp"
168 /*@
169     DMSetUp - sets up the data structures inside a DM object
170 
171     Collective on DM
172 
173     Input Parameter:
174 .   dm - the DM object to setup
175 
176     Level: developer
177 
178 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()
179 
180 @*/
181 PetscErrorCode  DMSetUp(DM dm)
182 {
183   PetscErrorCode ierr;
184 
185   PetscFunctionBegin;
186   if (dm->ops->setup) {
187     ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr);
188   }
189   PetscFunctionReturn(0);
190 }
191 
192 #undef __FUNCT__
193 #define __FUNCT__ "DMSetFromOptions"
194 /*@
195     DMSetFromOptions - sets parameters in a DM from the options database
196 
197     Collective on DM
198 
199     Input Parameter:
200 .   dm - the DM object to set options for
201 
202     Options Database:
203 .   -dm_preallocate_only: Only preallocate the matrix for DMGetMatrix(), but do not fill it with zeros
204 
205     Level: developer
206 
207 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()
208 
209 @*/
210 PetscErrorCode  DMSetFromOptions(DM dm)
211 {
212   PetscErrorCode ierr;
213 
214   PetscFunctionBegin;
215   ierr = PetscOptionsGetBool(((PetscObject) dm)->prefix, "-dm_preallocate_only", &dm->prealloc_only, PETSC_NULL);CHKERRQ(ierr);
216   if (dm->ops->setfromoptions) {
217     ierr = (*dm->ops->setfromoptions)(dm);CHKERRQ(ierr);
218   }
219   PetscFunctionReturn(0);
220 }
221 
222 #undef __FUNCT__
223 #define __FUNCT__ "DMView"
224 /*@C
225     DMView - Views a vector packer or DMDA.
226 
227     Collective on DM
228 
229     Input Parameter:
230 +   dm - the DM object to view
231 -   v - the viewer
232 
233     Level: developer
234 
235 .seealso DMDestroy(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()
236 
237 @*/
238 PetscErrorCode  DMView(DM dm,PetscViewer v)
239 {
240   PetscErrorCode ierr;
241 
242   PetscFunctionBegin;
243  if (!v) {
244     ierr = PetscViewerASCIIGetStdout(((PetscObject)dm)->comm,&v);CHKERRQ(ierr);
245   }
246   if (dm->ops->view) {
247     ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr);
248   }
249   PetscFunctionReturn(0);
250 }
251 
252 #undef __FUNCT__
253 #define __FUNCT__ "DMCreateGlobalVector"
254 /*@
255     DMCreateGlobalVector - Creates a global vector from a DMDA or DMComposite object
256 
257     Collective on DM
258 
259     Input Parameter:
260 .   dm - the DM object
261 
262     Output Parameter:
263 .   vec - the global vector
264 
265     Level: developer
266 
267 .seealso DMDestroy(), DMView(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()
268 
269 @*/
270 PetscErrorCode  DMCreateGlobalVector(DM dm,Vec *vec)
271 {
272   PetscErrorCode ierr;
273 
274   PetscFunctionBegin;
275   ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr);
276   PetscFunctionReturn(0);
277 }
278 
279 #undef __FUNCT__
280 #define __FUNCT__ "DMCreateLocalVector"
281 /*@
282     DMCreateLocalVector - Creates a local vector from a DMDA or DMComposite object
283 
284     Not Collective
285 
286     Input Parameter:
287 .   dm - the DM object
288 
289     Output Parameter:
290 .   vec - the local vector
291 
292     Level: developer
293 
294 .seealso DMDestroy(), DMView(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()
295 
296 @*/
297 PetscErrorCode  DMCreateLocalVector(DM dm,Vec *vec)
298 {
299   PetscErrorCode ierr;
300 
301   PetscFunctionBegin;
302   ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr);
303   PetscFunctionReturn(0);
304 }
305 
306 #undef __FUNCT__
307 #define __FUNCT__ "DMGetLocalToGlobalMapping"
308 /*@
309    DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM.
310 
311    Collective on DM
312 
313    Input Parameter:
314 .  dm - the DM that provides the mapping
315 
316    Output Parameter:
317 .  ltog - the mapping
318 
319    Level: intermediate
320 
321    Notes:
322    This mapping can then be used by VecSetLocalToGlobalMapping() or
323    MatSetLocalToGlobalMapping().
324 
325 .seealso: DMCreateLocalVector(), DMGetLocalToGlobalMappingBlock()
326 @*/
327 PetscErrorCode  DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog)
328 {
329   PetscErrorCode ierr;
330 
331   PetscFunctionBegin;
332   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
333   PetscValidPointer(ltog,2);
334   if (!dm->ltogmap) {
335     if (!dm->ops->createlocaltoglobalmapping) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping");
336     ierr = (*dm->ops->createlocaltoglobalmapping)(dm);CHKERRQ(ierr);
337   }
338   *ltog = dm->ltogmap;
339   PetscFunctionReturn(0);
340 }
341 
342 #undef __FUNCT__
343 #define __FUNCT__ "DMGetLocalToGlobalMappingBlock"
344 /*@
345    DMGetLocalToGlobalMappingBlock - Accesses the blocked local-to-global mapping in a DM.
346 
347    Collective on DM
348 
349    Input Parameter:
350 .  da - the distributed array that provides the mapping
351 
352    Output Parameter:
353 .  ltog - the block mapping
354 
355    Level: intermediate
356 
357    Notes:
358    This mapping can then be used by VecSetLocalToGlobalMappingBlock() or
359    MatSetLocalToGlobalMappingBlock().
360 
361 .seealso: DMCreateLocalVector(), DMGetLocalToGlobalMapping(), DMGetBlockSize(), VecSetBlockSize(), MatSetBlockSize()
362 @*/
363 PetscErrorCode  DMGetLocalToGlobalMappingBlock(DM dm,ISLocalToGlobalMapping *ltog)
364 {
365   PetscErrorCode ierr;
366 
367   PetscFunctionBegin;
368   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
369   PetscValidPointer(ltog,2);
370   if (!dm->ltogmapb) {
371     PetscInt bs;
372     ierr = DMGetBlockSize(dm,&bs);CHKERRQ(ierr);
373     if (bs > 1) {
374       if (!dm->ops->createlocaltoglobalmappingblock) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"DM can not create LocalToGlobalMappingBlock");
375       ierr = (*dm->ops->createlocaltoglobalmappingblock)(dm);CHKERRQ(ierr);
376     } else {
377       ierr = DMGetLocalToGlobalMapping(dm,&dm->ltogmapb);CHKERRQ(ierr);
378       ierr = PetscObjectReference((PetscObject)dm->ltogmapb);CHKERRQ(ierr);
379     }
380   }
381   *ltog = dm->ltogmapb;
382   PetscFunctionReturn(0);
383 }
384 
385 #undef __FUNCT__
386 #define __FUNCT__ "DMGetBlockSize"
387 /*@
388    DMGetBlockSize - Gets the inherent block size associated with a DM
389 
390    Not Collective
391 
392    Input Parameter:
393 .  dm - the DM with block structure
394 
395    Output Parameter:
396 .  bs - the block size, 1 implies no exploitable block structure
397 
398    Level: intermediate
399 
400 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMappingBlock()
401 @*/
402 PetscErrorCode  DMGetBlockSize(DM dm,PetscInt *bs)
403 {
404   PetscFunctionBegin;
405   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
406   PetscValidPointer(bs,2);
407   if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet");
408   *bs = dm->bs;
409   PetscFunctionReturn(0);
410 }
411 
412 #undef __FUNCT__
413 #define __FUNCT__ "DMGetInterpolation"
414 /*@
415     DMGetInterpolation - Gets interpolation matrix between two DMDA or DMComposite objects
416 
417     Collective on DM
418 
419     Input Parameter:
420 +   dm1 - the DM object
421 -   dm2 - the second, finer DM object
422 
423     Output Parameter:
424 +  mat - the interpolation
425 -  vec - the scaling (optional)
426 
427     Level: developer
428 
429 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetColoring(), DMGetMatrix()
430 
431 @*/
432 PetscErrorCode  DMGetInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec)
433 {
434   PetscErrorCode ierr;
435 
436   PetscFunctionBegin;
437   ierr = (*dm1->ops->getinterpolation)(dm1,dm2,mat,vec);CHKERRQ(ierr);
438   PetscFunctionReturn(0);
439 }
440 
441 #undef __FUNCT__
442 #define __FUNCT__ "DMGetInjection"
443 /*@
444     DMGetInjection - Gets injection matrix between two DMDA or DMComposite objects
445 
446     Collective on DM
447 
448     Input Parameter:
449 +   dm1 - the DM object
450 -   dm2 - the second, finer DM object
451 
452     Output Parameter:
453 .   ctx - the injection
454 
455     Level: developer
456 
457 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetColoring(), DMGetMatrix(), DMGetInterpolation()
458 
459 @*/
460 PetscErrorCode  DMGetInjection(DM dm1,DM dm2,VecScatter *ctx)
461 {
462   PetscErrorCode ierr;
463 
464   PetscFunctionBegin;
465   ierr = (*dm1->ops->getinjection)(dm1,dm2,ctx);CHKERRQ(ierr);
466   PetscFunctionReturn(0);
467 }
468 
469 #undef __FUNCT__
470 #define __FUNCT__ "DMGetColoring"
471 /*@C
472     DMGetColoring - Gets coloring for a DMDA or DMComposite
473 
474     Collective on DM
475 
476     Input Parameter:
477 +   dm - the DM object
478 .   ctype - IS_COLORING_GHOSTED or IS_COLORING_GLOBAL
479 -   matype - either MATAIJ or MATBAIJ
480 
481     Output Parameter:
482 .   coloring - the coloring
483 
484     Level: developer
485 
486 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetMatrix()
487 
488 C@*/
489 PetscErrorCode  DMGetColoring(DM dm,ISColoringType ctype,const MatType mtype,ISColoring *coloring)
490 {
491   PetscErrorCode ierr;
492 
493   PetscFunctionBegin;
494   if (!dm->ops->getcoloring) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No coloring for this type of DM yet");
495   ierr = (*dm->ops->getcoloring)(dm,ctype,mtype,coloring);CHKERRQ(ierr);
496   PetscFunctionReturn(0);
497 }
498 
499 #undef __FUNCT__
500 #define __FUNCT__ "DMGetMatrix"
501 /*@C
502     DMGetMatrix - Gets empty Jacobian for a DMDA or DMComposite
503 
504     Collective on DM
505 
506     Input Parameter:
507 +   dm - the DM object
508 -   mtype - Supported types are MATSEQAIJ, MATMPIAIJ, MATSEQBAIJ, MATMPIBAIJ, or
509             any type which inherits from one of these (such as MATAIJ)
510 
511     Output Parameter:
512 .   mat - the empty Jacobian
513 
514     Level: developer
515 
516     Notes: This properly preallocates the number of nonzeros in the sparse matrix so you
517        do not need to do it yourself.
518 
519        By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
520        the nonzero pattern call DMDASetMatPreallocateOnly()
521 
522        For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used
523        internally by PETSc.
524 
525        For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires
526        the indices for the global numbering for DMDAs which is complicated.
527 
528 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetMatrix()
529 
530 @*/
531 PetscErrorCode  DMGetMatrix(DM dm,const MatType mtype,Mat *mat)
532 {
533   PetscErrorCode ierr;
534   char           ttype[256];
535   PetscBool      flg;
536 
537   PetscFunctionBegin;
538   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
539   PetscValidPointer(mat,3);
540   ierr = PetscStrncpy(ttype,mtype,sizeof ttype);CHKERRQ(ierr);
541   ttype[sizeof ttype-1] = 0;
542   ierr = PetscOptionsBegin(((PetscObject)dm)->comm,((PetscObject)dm)->prefix,"DM options","Mat");CHKERRQ(ierr);
543   ierr = PetscOptionsList("-dm_mat_type","Matrix type","MatSetType",MatList,ttype,ttype,sizeof ttype,&flg);CHKERRQ(ierr);
544   ierr = PetscOptionsEnd();
545   if (flg || mtype) {
546     ierr = (*dm->ops->getmatrix)(dm,ttype,mat);CHKERRQ(ierr);
547   } else {                      /* Let the implementation decide */
548     ierr = (*dm->ops->getmatrix)(dm,PETSC_NULL,mat);CHKERRQ(ierr);
549   }
550   PetscFunctionReturn(0);
551 }
552 
553 #undef __FUNCT__
554 #define __FUNCT__ "DMSetMatrixPreallocateOnly"
555 /*@
556   DMSetMatrixPreallocateOnly - When DMGetMatrix() is called the matrix will be properly
557     preallocated but the nonzero structure and zero values will not be set.
558 
559   Logically Collective on DMDA
560 
561   Input Parameter:
562 + dm - the DM
563 - only - PETSC_TRUE if only want preallocation
564 
565   Level: developer
566 .seealso DMGetMatrix()
567 @*/
568 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
569 {
570   PetscFunctionBegin;
571   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
572   dm->prealloc_only = only;
573   PetscFunctionReturn(0);
574 }
575 
576 #undef __FUNCT__
577 #define __FUNCT__ "DMRefine"
578 /*@
579     DMRefine - Refines a DM object
580 
581     Collective on DM
582 
583     Input Parameter:
584 +   dm - the DM object
585 -   comm - the communicator to contain the new DM object (or PETSC_NULL)
586 
587     Output Parameter:
588 .   dmf - the refined DM
589 
590     Level: developer
591 
592 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()
593 
594 @*/
595 PetscErrorCode  DMRefine(DM dm,MPI_Comm comm,DM *dmf)
596 {
597   PetscErrorCode ierr;
598 
599   PetscFunctionBegin;
600   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
601   ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr);
602   (*dmf)->levelup = dm->levelup + 1;
603   PetscFunctionReturn(0);
604 }
605 
606 #undef __FUNCT__
607 #define __FUNCT__ "DMGlobalToLocalBegin"
608 /*@
609     DMGlobalToLocalBegin - Begins updating local vectors from global vector
610 
611     Neighbor-wise Collective on DM
612 
613     Input Parameters:
614 +   dm - the DM object
615 .   g - the global vector
616 .   mode - INSERT_VALUES or ADD_VALUES
617 -   l - the local vector
618 
619 
620     Level: beginner
621 
622 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
623 
624 @*/
625 PetscErrorCode  DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
626 {
627   PetscErrorCode ierr;
628 
629   PetscFunctionBegin;
630   ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode,l);CHKERRQ(ierr);
631   PetscFunctionReturn(0);
632 }
633 
634 #undef __FUNCT__
635 #define __FUNCT__ "DMGlobalToLocalEnd"
636 /*@
637     DMGlobalToLocalEnd - Ends updating local vectors from global vector
638 
639     Neighbor-wise Collective on DM
640 
641     Input Parameters:
642 +   dm - the DM object
643 .   g - the global vector
644 .   mode - INSERT_VALUES or ADD_VALUES
645 -   l - the local vector
646 
647 
648     Level: beginner
649 
650 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
651 
652 @*/
653 PetscErrorCode  DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
654 {
655   PetscErrorCode ierr;
656 
657   PetscFunctionBegin;
658   ierr = (*dm->ops->globaltolocalend)(dm,g,mode,l);CHKERRQ(ierr);
659   PetscFunctionReturn(0);
660 }
661 
662 #undef __FUNCT__
663 #define __FUNCT__ "DMLocalToGlobalBegin"
664 /*@
665     DMLocalToGlobalBegin - updates global vectors from local vectors
666 
667     Neighbor-wise Collective on DM
668 
669     Input Parameters:
670 +   dm - the DM object
671 .   l - the local vector
672 .   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
673            base point.
674 - - the global vector
675 
676     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
677            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
678            global array to the final global array with VecAXPY().
679 
680     Level: beginner
681 
682 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()
683 
684 @*/
685 PetscErrorCode  DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
686 {
687   PetscErrorCode ierr;
688 
689   PetscFunctionBegin;
690   ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode,g);CHKERRQ(ierr);
691   PetscFunctionReturn(0);
692 }
693 
694 #undef __FUNCT__
695 #define __FUNCT__ "DMLocalToGlobalEnd"
696 /*@
697     DMLocalToGlobalEnd - updates global vectors from local vectors
698 
699     Neighbor-wise Collective on DM
700 
701     Input Parameters:
702 +   dm - the DM object
703 .   l - the local vector
704 .   mode - INSERT_VALUES or ADD_VALUES
705 -   g - the global vector
706 
707 
708     Level: beginner
709 
710 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()
711 
712 @*/
713 PetscErrorCode  DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
714 {
715   PetscErrorCode ierr;
716 
717   PetscFunctionBegin;
718   ierr = (*dm->ops->localtoglobalend)(dm,l,mode,g);CHKERRQ(ierr);
719   PetscFunctionReturn(0);
720 }
721 
722 #undef __FUNCT__
723 #define __FUNCT__ "DMComputeJacobianDefault"
724 /*@
725     DMComputeJacobianDefault - computes the Jacobian using the DMComputeFunction() if Jacobian computer is not provided
726 
727     Collective on DM
728 
729     Input Parameter:
730 +   dm - the DM object
731 .   x - location to compute Jacobian at; may be ignored for linear problems
732 .   A - matrix that defines the operator for the linear solve
733 -   B - the matrix used to construct the preconditioner
734 
735     Level: developer
736 
737 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetContext(), DMSetInitialGuess(),
738          DMSetFunction()
739 
740 @*/
741 PetscErrorCode  DMComputeJacobianDefault(DM dm,Vec x,Mat A,Mat B,MatStructure *stflag)
742 {
743   PetscErrorCode ierr;
744   PetscFunctionBegin;
745   *stflag = SAME_NONZERO_PATTERN;
746   ierr  = MatFDColoringApply(B,dm->fd,x,stflag,dm);CHKERRQ(ierr);
747   if (A != B) {
748     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
749     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
750   }
751   PetscFunctionReturn(0);
752 }
753 
754 #undef __FUNCT__
755 #define __FUNCT__ "DMCoarsen"
756 /*@
757     DMCoarsen - Coarsens a DM object
758 
759     Collective on DM
760 
761     Input Parameter:
762 +   dm - the DM object
763 -   comm - the communicator to contain the new DM object (or PETSC_NULL)
764 
765     Output Parameter:
766 .   dmc - the coarsened DM
767 
768     Level: developer
769 
770 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()
771 
772 @*/
773 PetscErrorCode  DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
774 {
775   PetscErrorCode ierr;
776 
777   PetscFunctionBegin;
778   ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr);
779   (*dmc)->ops->initialguess = dm->ops->initialguess;
780   (*dmc)->ops->function     = dm->ops->function;
781   (*dmc)->ops->functionj    = dm->ops->functionj;
782   if (dm->ops->jacobian != DMComputeJacobianDefault) {
783     (*dmc)->ops->jacobian     = dm->ops->jacobian;
784   }
785   (*dmc)->leveldown = dm->leveldown + 1;
786   PetscFunctionReturn(0);
787 }
788 
789 #undef __FUNCT__
790 #define __FUNCT__ "DMRefineHierarchy"
791 /*@C
792     DMRefineHierarchy - Refines a DM object, all levels at once
793 
794     Collective on DM
795 
796     Input Parameter:
797 +   dm - the DM object
798 -   nlevels - the number of levels of refinement
799 
800     Output Parameter:
801 .   dmf - the refined DM hierarchy
802 
803     Level: developer
804 
805 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()
806 
807 @*/
808 PetscErrorCode  DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
809 {
810   PetscErrorCode ierr;
811 
812   PetscFunctionBegin;
813   if (nlevels < 0) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
814   if (nlevels == 0) PetscFunctionReturn(0);
815   if (dm->ops->refinehierarchy) {
816     ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr);
817   } else if (dm->ops->refine) {
818     PetscInt i;
819 
820     ierr = DMRefine(dm,((PetscObject)dm)->comm,&dmf[0]);CHKERRQ(ierr);
821     for (i=1; i<nlevels; i++) {
822       ierr = DMRefine(dmf[i-1],((PetscObject)dm)->comm,&dmf[i]);CHKERRQ(ierr);
823     }
824   } else {
825     SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
826   }
827   PetscFunctionReturn(0);
828 }
829 
830 #undef __FUNCT__
831 #define __FUNCT__ "DMCoarsenHierarchy"
832 /*@C
833     DMCoarsenHierarchy - Coarsens a DM object, all levels at once
834 
835     Collective on DM
836 
837     Input Parameter:
838 +   dm - the DM object
839 -   nlevels - the number of levels of coarsening
840 
841     Output Parameter:
842 .   dmc - the coarsened DM hierarchy
843 
844     Level: developer
845 
846 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()
847 
848 @*/
849 PetscErrorCode  DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
850 {
851   PetscErrorCode ierr;
852 
853   PetscFunctionBegin;
854   if (nlevels < 0) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
855   if (nlevels == 0) PetscFunctionReturn(0);
856   PetscValidPointer(dmc,3);
857   if (dm->ops->coarsenhierarchy) {
858     ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr);
859   } else if (dm->ops->coarsen) {
860     PetscInt i;
861 
862     ierr = DMCoarsen(dm,((PetscObject)dm)->comm,&dmc[0]);CHKERRQ(ierr);
863     for (i=1; i<nlevels; i++) {
864       ierr = DMCoarsen(dmc[i-1],((PetscObject)dm)->comm,&dmc[i]);CHKERRQ(ierr);
865     }
866   } else {
867     SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
868   }
869   PetscFunctionReturn(0);
870 }
871 
872 #undef __FUNCT__
873 #define __FUNCT__ "DMGetAggregates"
874 /*@
875    DMGetAggregates - Gets the aggregates that map between
876    grids associated with two DMs.
877 
878    Collective on DM
879 
880    Input Parameters:
881 +  dmc - the coarse grid DM
882 -  dmf - the fine grid DM
883 
884    Output Parameters:
885 .  rest - the restriction matrix (transpose of the projection matrix)
886 
887    Level: intermediate
888 
889 .keywords: interpolation, restriction, multigrid
890 
891 .seealso: DMRefine(), DMGetInjection(), DMGetInterpolation()
892 @*/
893 PetscErrorCode  DMGetAggregates(DM dmc, DM dmf, Mat *rest)
894 {
895   PetscErrorCode ierr;
896 
897   PetscFunctionBegin;
898   ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr);
899   PetscFunctionReturn(0);
900 }
901 
902 #undef __FUNCT__
903 #define __FUNCT__ "DMSetContext"
904 /*@
905     DMSetContext - Set a user context into a DM object
906 
907     Not Collective
908 
909     Input Parameters:
910 +   dm - the DM object
911 -   ctx - the user context
912 
913     Level: intermediate
914 
915 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetContext()
916 
917 @*/
918 PetscErrorCode  DMSetContext(DM dm,void *ctx)
919 {
920   PetscFunctionBegin;
921   dm->ctx = ctx;
922   PetscFunctionReturn(0);
923 }
924 
925 #undef __FUNCT__
926 #define __FUNCT__ "DMGetContext"
927 /*@
928     DMGetContext - Gets a user context from a DM object
929 
930     Not Collective
931 
932     Input Parameter:
933 .   dm - the DM object
934 
935     Output Parameter:
936 .   ctx - the user context
937 
938     Level: intermediate
939 
940 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetContext()
941 
942 @*/
943 PetscErrorCode  DMGetContext(DM dm,void **ctx)
944 {
945   PetscFunctionBegin;
946   *ctx = dm->ctx;
947   PetscFunctionReturn(0);
948 }
949 
950 #undef __FUNCT__
951 #define __FUNCT__ "DMSetInitialGuess"
952 /*@
953     DMSetInitialGuess - sets a function to compute an initial guess vector entries for the solvers
954 
955     Logically Collective on DM
956 
957     Input Parameter:
958 +   dm - the DM object to destroy
959 -   f - the function to compute the initial guess
960 
961     Level: intermediate
962 
963 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetContext(), DMSetFunction(), DMSetJacobian()
964 
965 @*/
966 PetscErrorCode  DMSetInitialGuess(DM dm,PetscErrorCode (*f)(DM,Vec))
967 {
968   PetscFunctionBegin;
969   dm->ops->initialguess = f;
970   PetscFunctionReturn(0);
971 }
972 
973 #undef __FUNCT__
974 #define __FUNCT__ "DMSetFunction"
975 /*@
976     DMSetFunction - sets a function to compute the right hand side vector entries for the KSP solver or nonlinear function for SNES
977 
978     Logically Collective on DM
979 
980     Input Parameter:
981 +   dm - the DM object
982 -   f - the function to compute (use PETSC_NULL to cancel a previous function that was set)
983 
984     Level: intermediate
985 
986     Notes: This sets both the function for function evaluations and the function used to compute Jacobians via finite differences if no Jacobian
987            computer is provided with DMSetJacobian(). Canceling cancels the function, but not the function used to compute the Jacobian.
988 
989 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetContext(), DMSetInitialGuess(),
990          DMSetJacobian()
991 
992 @*/
993 PetscErrorCode  DMSetFunction(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
994 {
995   PetscFunctionBegin;
996   dm->ops->function = f;
997   if (f) {
998     dm->ops->functionj = f;
999   }
1000   PetscFunctionReturn(0);
1001 }
1002 
1003 #undef __FUNCT__
1004 #define __FUNCT__ "DMSetJacobian"
1005 /*@
1006     DMSetJacobian - sets a function to compute the matrix entries for the KSP solver or Jacobian for SNES
1007 
1008     Logically Collective on DM
1009 
1010     Input Parameter:
1011 +   dm - the DM object to destroy
1012 -   f - the function to compute the matrix entries
1013 
1014     Level: intermediate
1015 
1016 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetContext(), DMSetInitialGuess(),
1017          DMSetFunction()
1018 
1019 @*/
1020 PetscErrorCode  DMSetJacobian(DM dm,PetscErrorCode (*f)(DM,Vec,Mat,Mat,MatStructure*))
1021 {
1022   PetscFunctionBegin;
1023   dm->ops->jacobian = f;
1024   PetscFunctionReturn(0);
1025 }
1026 
1027 #undef __FUNCT__
1028 #define __FUNCT__ "DMComputeInitialGuess"
1029 /*@
1030     DMComputeInitialGuess - computes an initial guess vector entries for the KSP solvers
1031 
1032     Collective on DM
1033 
1034     Input Parameter:
1035 +   dm - the DM object to destroy
1036 -   x - the vector to hold the initial guess values
1037 
1038     Level: developer
1039 
1040 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetContext(), DMSetRhs(), DMSetMat()
1041 
1042 @*/
1043 PetscErrorCode  DMComputeInitialGuess(DM dm,Vec x)
1044 {
1045   PetscErrorCode ierr;
1046   PetscFunctionBegin;
1047   if (!dm->ops->initialguess) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to provide function with DMSetInitialGuess()");
1048   ierr = (*dm->ops->initialguess)(dm,x);CHKERRQ(ierr);
1049   PetscFunctionReturn(0);
1050 }
1051 
1052 #undef __FUNCT__
1053 #define __FUNCT__ "DMHasInitialGuess"
1054 /*@
1055     DMHasInitialGuess - does the DM object have an initial guess function
1056 
1057     Not Collective
1058 
1059     Input Parameter:
1060 .   dm - the DM object to destroy
1061 
1062     Output Parameter:
1063 .   flg - PETSC_TRUE if function exists
1064 
1065     Level: developer
1066 
1067 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetContext(), DMSetFunction(), DMSetJacobian()
1068 
1069 @*/
1070 PetscErrorCode  DMHasInitialGuess(DM dm,PetscBool  *flg)
1071 {
1072   PetscFunctionBegin;
1073   *flg =  (dm->ops->initialguess) ? PETSC_TRUE : PETSC_FALSE;
1074   PetscFunctionReturn(0);
1075 }
1076 
1077 #undef __FUNCT__
1078 #define __FUNCT__ "DMHasFunction"
1079 /*@
1080     DMHasFunction - does the DM object have a function
1081 
1082     Not Collective
1083 
1084     Input Parameter:
1085 .   dm - the DM object to destroy
1086 
1087     Output Parameter:
1088 .   flg - PETSC_TRUE if function exists
1089 
1090     Level: developer
1091 
1092 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetContext(), DMSetFunction(), DMSetJacobian()
1093 
1094 @*/
1095 PetscErrorCode  DMHasFunction(DM dm,PetscBool  *flg)
1096 {
1097   PetscFunctionBegin;
1098   *flg =  (dm->ops->function) ? PETSC_TRUE : PETSC_FALSE;
1099   PetscFunctionReturn(0);
1100 }
1101 
1102 #undef __FUNCT__
1103 #define __FUNCT__ "DMHasJacobian"
1104 /*@
1105     DMHasJacobian - does the DM object have a matrix function
1106 
1107     Not Collective
1108 
1109     Input Parameter:
1110 .   dm - the DM object to destroy
1111 
1112     Output Parameter:
1113 .   flg - PETSC_TRUE if function exists
1114 
1115     Level: developer
1116 
1117 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetContext(), DMSetFunction(), DMSetJacobian()
1118 
1119 @*/
1120 PetscErrorCode  DMHasJacobian(DM dm,PetscBool  *flg)
1121 {
1122   PetscFunctionBegin;
1123   *flg =  (dm->ops->jacobian) ? PETSC_TRUE : PETSC_FALSE;
1124   PetscFunctionReturn(0);
1125 }
1126 
1127 #undef __FUNCT__
1128 #define __FUNCT__ "DMComputeFunction"
1129 /*@
1130     DMComputeFunction - computes the right hand side vector entries for the KSP solver or nonlinear function for SNES
1131 
1132     Collective on DM
1133 
1134     Input Parameter:
1135 +   dm - the DM object to destroy
1136 .   x - the location where the function is evaluationed, may be ignored for linear problems
1137 -   b - the vector to hold the right hand side entries
1138 
1139     Level: developer
1140 
1141 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetContext(), DMSetInitialGuess(),
1142          DMSetJacobian()
1143 
1144 @*/
1145 PetscErrorCode  DMComputeFunction(DM dm,Vec x,Vec b)
1146 {
1147   PetscErrorCode ierr;
1148   PetscFunctionBegin;
1149   if (!dm->ops->function) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to provide function with DMSetFunction()");
1150   if (!x) x = dm->x;
1151   ierr = (*dm->ops->function)(dm,x,b);CHKERRQ(ierr);
1152   PetscFunctionReturn(0);
1153 }
1154 
1155 
1156 #undef __FUNCT__
1157 #define __FUNCT__ "DMComputeJacobian"
1158 /*@
1159     DMComputeJacobian - compute the matrix entries for the solver
1160 
1161     Collective on DM
1162 
1163     Input Parameter:
1164 +   dm - the DM object
1165 .   x - location to compute Jacobian at; may be ignored for linear problems
1166 .   A - matrix that defines the operator for the linear solve
1167 -   B - the matrix used to construct the preconditioner
1168 
1169     Level: developer
1170 
1171 .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetContext(), DMSetInitialGuess(),
1172          DMSetFunction()
1173 
1174 @*/
1175 PetscErrorCode  DMComputeJacobian(DM dm,Vec x,Mat A,Mat B,MatStructure *stflag)
1176 {
1177   PetscErrorCode ierr;
1178 
1179   PetscFunctionBegin;
1180   if (!dm->ops->jacobian) {
1181     ISColoring    coloring;
1182     MatFDColoring fd;
1183 
1184     ierr = DMGetColoring(dm,IS_COLORING_GHOSTED,MATAIJ,&coloring);CHKERRQ(ierr);
1185     ierr = MatFDColoringCreate(B,coloring,&fd);CHKERRQ(ierr);
1186     ierr = ISColoringDestroy(&coloring);CHKERRQ(ierr);
1187     ierr = MatFDColoringSetFunction(fd,(PetscErrorCode (*)(void))dm->ops->functionj,dm);CHKERRQ(ierr);
1188     dm->fd = fd;
1189     dm->ops->jacobian = DMComputeJacobianDefault;
1190 
1191     if (!dm->x) {
1192       ierr = MatGetVecs(B,&dm->x,PETSC_NULL);CHKERRQ(ierr);
1193     }
1194   }
1195   if (!x) x = dm->x;
1196   ierr = (*dm->ops->jacobian)(dm,x,A,B,stflag);CHKERRQ(ierr);
1197   PetscFunctionReturn(0);
1198 }
1199 
1200 PetscFList DMList                       = PETSC_NULL;
1201 PetscBool  DMRegisterAllCalled          = PETSC_FALSE;
1202 
1203 #undef __FUNCT__
1204 #define __FUNCT__ "DMSetType"
1205 /*@C
1206   DMSetType - Builds a DM, for a particular DM implementation.
1207 
1208   Collective on DM
1209 
1210   Input Parameters:
1211 + dm     - The DM object
1212 - method - The name of the DM type
1213 
1214   Options Database Key:
1215 . -dm_type <type> - Sets the DM type; use -help for a list of available types
1216 
1217   Notes:
1218   See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).
1219 
1220   Level: intermediate
1221 
1222 .keywords: DM, set, type
1223 .seealso: DMGetType(), DMCreate()
1224 @*/
1225 PetscErrorCode  DMSetType(DM dm, const DMType method)
1226 {
1227   PetscErrorCode (*r)(DM);
1228   PetscBool      match;
1229   PetscErrorCode ierr;
1230 
1231   PetscFunctionBegin;
1232   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
1233   ierr = PetscTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr);
1234   if (match) PetscFunctionReturn(0);
1235 
1236   if (!DMRegisterAllCalled) {ierr = DMRegisterAll(PETSC_NULL);CHKERRQ(ierr);}
1237   ierr = PetscFListFind(DMList, ((PetscObject)dm)->comm, method,PETSC_TRUE,(void (**)(void)) &r);CHKERRQ(ierr);
1238   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
1239 
1240   if (dm->ops->destroy) {
1241     ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr);
1242   }
1243   ierr = (*r)(dm);CHKERRQ(ierr);
1244   ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr);
1245   PetscFunctionReturn(0);
1246 }
1247 
1248 #undef __FUNCT__
1249 #define __FUNCT__ "DMGetType"
1250 /*@C
1251   DMGetType - Gets the DM type name (as a string) from the DM.
1252 
1253   Not Collective
1254 
1255   Input Parameter:
1256 . dm  - The DM
1257 
1258   Output Parameter:
1259 . type - The DM type name
1260 
1261   Level: intermediate
1262 
1263 .keywords: DM, get, type, name
1264 .seealso: DMSetType(), DMCreate()
1265 @*/
1266 PetscErrorCode  DMGetType(DM dm, const DMType *type)
1267 {
1268   PetscErrorCode ierr;
1269 
1270   PetscFunctionBegin;
1271   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
1272   PetscValidCharPointer(type,2);
1273   if (!DMRegisterAllCalled) {
1274     ierr = DMRegisterAll(PETSC_NULL);CHKERRQ(ierr);
1275   }
1276   *type = ((PetscObject)dm)->type_name;
1277   PetscFunctionReturn(0);
1278 }
1279 
1280 #undef __FUNCT__
1281 #define __FUNCT__ "DMConvert"
1282 /*@C
1283   DMConvert - Converts a DM to another DM, either of the same or different type.
1284 
1285   Collective on DM
1286 
1287   Input Parameters:
1288 + dm - the DM
1289 - newtype - new DM type (use "same" for the same type)
1290 
1291   Output Parameter:
1292 . M - pointer to new DM
1293 
1294   Notes:
1295   Cannot be used to convert a sequential DM to parallel or parallel to sequential,
1296   the MPI communicator of the generated DM is always the same as the communicator
1297   of the input DM.
1298 
1299   Level: intermediate
1300 
1301 .seealso: DMCreate()
1302 @*/
1303 PetscErrorCode DMConvert(DM dm, const DMType newtype, DM *M)
1304 {
1305   DM             B;
1306   char           convname[256];
1307   PetscBool      sametype, issame;
1308   PetscErrorCode ierr;
1309 
1310   PetscFunctionBegin;
1311   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1312   PetscValidType(dm,1);
1313   PetscValidPointer(M,3);
1314   ierr = PetscTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr);
1315   ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr);
1316   {
1317     PetscErrorCode (*conv)(DM, const DMType, DM *) = PETSC_NULL;
1318 
1319     /*
1320        Order of precedence:
1321        1) See if a specialized converter is known to the current DM.
1322        2) See if a specialized converter is known to the desired DM class.
1323        3) See if a good general converter is registered for the desired class
1324        4) See if a good general converter is known for the current matrix.
1325        5) Use a really basic converter.
1326     */
1327 
1328     /* 1) See if a specialized converter is known to the current DM and the desired class */
1329     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
1330     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
1331     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
1332     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
1333     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
1334     ierr = PetscObjectQueryFunction((PetscObject)dm,convname,(void (**)(void))&conv);CHKERRQ(ierr);
1335     if (conv) goto foundconv;
1336 
1337     /* 2)  See if a specialized converter is known to the desired DM class. */
1338     ierr = DMCreate(((PetscObject) dm)->comm, &B);CHKERRQ(ierr);
1339     ierr = DMSetType(B, newtype);CHKERRQ(ierr);
1340     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
1341     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
1342     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
1343     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
1344     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
1345     ierr = PetscObjectQueryFunction((PetscObject)B,convname,(void (**)(void))&conv);CHKERRQ(ierr);
1346     if (conv) {
1347       ierr = DMDestroy(&B);CHKERRQ(ierr);
1348       goto foundconv;
1349     }
1350 
1351 #if 0
1352     /* 3) See if a good general converter is registered for the desired class */
1353     conv = B->ops->convertfrom;
1354     ierr = DMDestroy(&B);CHKERRQ(ierr);
1355     if (conv) goto foundconv;
1356 
1357     /* 4) See if a good general converter is known for the current matrix */
1358     if (dm->ops->convert) {
1359       conv = dm->ops->convert;
1360     }
1361     if (conv) goto foundconv;
1362 #endif
1363 
1364     /* 5) Use a really basic converter. */
1365     SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);
1366 
1367     foundconv:
1368     ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
1369     ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr);
1370     ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
1371   }
1372   ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr);
1373   PetscFunctionReturn(0);
1374 }
1375 
1376 /*--------------------------------------------------------------------------------------------------------------------*/
1377 
1378 #undef __FUNCT__
1379 #define __FUNCT__ "DMRegister"
1380 /*@C
1381   DMRegister - See DMRegisterDynamic()
1382 
1383   Level: advanced
1384 @*/
1385 PetscErrorCode  DMRegister(const char sname[], const char path[], const char name[], PetscErrorCode (*function)(DM))
1386 {
1387   char fullname[PETSC_MAX_PATH_LEN];
1388   PetscErrorCode ierr;
1389 
1390   PetscFunctionBegin;
1391   ierr = PetscStrcpy(fullname, path);CHKERRQ(ierr);
1392   ierr = PetscStrcat(fullname, ":");CHKERRQ(ierr);
1393   ierr = PetscStrcat(fullname, name);CHKERRQ(ierr);
1394   ierr = PetscFListAdd(&DMList, sname, fullname, (void (*)(void)) function);CHKERRQ(ierr);
1395   PetscFunctionReturn(0);
1396 }
1397 
1398 
1399 /*--------------------------------------------------------------------------------------------------------------------*/
1400 #undef __FUNCT__
1401 #define __FUNCT__ "DMRegisterDestroy"
1402 /*@C
1403    DMRegisterDestroy - Frees the list of DM methods that were registered by DMRegister()/DMRegisterDynamic().
1404 
1405    Not Collective
1406 
1407    Level: advanced
1408 
1409 .keywords: DM, register, destroy
1410 .seealso: DMRegister(), DMRegisterAll(), DMRegisterDynamic()
1411 @*/
1412 PetscErrorCode  DMRegisterDestroy(void)
1413 {
1414   PetscErrorCode ierr;
1415 
1416   PetscFunctionBegin;
1417   ierr = PetscFListDestroy(&DMList);CHKERRQ(ierr);
1418   DMRegisterAllCalled = PETSC_FALSE;
1419   PetscFunctionReturn(0);
1420 }
1421 
1422 #if defined(PETSC_HAVE_MATLAB_ENGINE)
1423 #include <mex.h>
1424 
1425 typedef struct {char *funcname; char *jacname; mxArray *ctx;} DMMatlabContext;
1426 
1427 #undef __FUNCT__
1428 #define __FUNCT__ "DMComputeFunction_Matlab"
1429 /*
1430    DMComputeFunction_Matlab - Calls the function that has been set with
1431                          DMSetFunctionMatlab().
1432 
1433    For linear problems x is null
1434 
1435 .seealso: DMSetFunction(), DMGetFunction()
1436 */
1437 PetscErrorCode  DMComputeFunction_Matlab(DM dm,Vec x,Vec y)
1438 {
1439   PetscErrorCode    ierr;
1440   DMMatlabContext   *sctx;
1441   int               nlhs = 1,nrhs = 4;
1442   mxArray	    *plhs[1],*prhs[4];
1443   long long int     lx = 0,ly = 0,ls = 0;
1444 
1445   PetscFunctionBegin;
1446   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1447   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
1448   PetscCheckSameComm(dm,1,y,3);
1449 
1450   /* call Matlab function in ctx with arguments x and y */
1451   ierr = DMGetContext(dm,(void**)&sctx);CHKERRQ(ierr);
1452   ierr = PetscMemcpy(&ls,&dm,sizeof(dm));CHKERRQ(ierr);
1453   ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr);
1454   ierr = PetscMemcpy(&ly,&y,sizeof(y));CHKERRQ(ierr);
1455   prhs[0] =  mxCreateDoubleScalar((double)ls);
1456   prhs[1] =  mxCreateDoubleScalar((double)lx);
1457   prhs[2] =  mxCreateDoubleScalar((double)ly);
1458   prhs[3] =  mxCreateString(sctx->funcname);
1459   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscDMComputeFunctionInternal");CHKERRQ(ierr);
1460   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
1461   mxDestroyArray(prhs[0]);
1462   mxDestroyArray(prhs[1]);
1463   mxDestroyArray(prhs[2]);
1464   mxDestroyArray(prhs[3]);
1465   mxDestroyArray(plhs[0]);
1466   PetscFunctionReturn(0);
1467 }
1468 
1469 
1470 #undef __FUNCT__
1471 #define __FUNCT__ "DMSetFunctionMatlab"
1472 /*
1473    DMSetFunctionMatlab - Sets the function evaluation routine
1474 
1475 */
1476 PetscErrorCode  DMSetFunctionMatlab(DM dm,const char *func)
1477 {
1478   PetscErrorCode    ierr;
1479   DMMatlabContext   *sctx;
1480 
1481   PetscFunctionBegin;
1482   /* currently sctx is memory bleed */
1483   ierr = DMGetContext(dm,(void**)&sctx);CHKERRQ(ierr);
1484   if (!sctx) {
1485     ierr = PetscMalloc(sizeof(DMMatlabContext),&sctx);CHKERRQ(ierr);
1486   }
1487   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
1488   ierr = DMSetContext(dm,sctx);CHKERRQ(ierr);
1489   ierr = DMSetFunction(dm,DMComputeFunction_Matlab);CHKERRQ(ierr);
1490   PetscFunctionReturn(0);
1491 }
1492 
1493 #undef __FUNCT__
1494 #define __FUNCT__ "DMComputeJacobian_Matlab"
1495 /*
1496    DMComputeJacobian_Matlab - Calls the function that has been set with
1497                          DMSetJacobianMatlab().
1498 
1499    For linear problems x is null
1500 
1501 .seealso: DMSetFunction(), DMGetFunction()
1502 */
1503 PetscErrorCode  DMComputeJacobian_Matlab(DM dm,Vec x,Mat A,Mat B,MatStructure *str)
1504 {
1505   PetscErrorCode    ierr;
1506   DMMatlabContext   *sctx;
1507   int               nlhs = 2,nrhs = 5;
1508   mxArray	    *plhs[2],*prhs[5];
1509   long long int     lx = 0,lA = 0,lB = 0,ls = 0;
1510 
1511   PetscFunctionBegin;
1512   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1513   PetscValidHeaderSpecific(A,MAT_CLASSID,3);
1514 
1515   /* call MATLAB function in ctx with arguments x, A, and B */
1516   ierr = DMGetContext(dm,(void**)&sctx);CHKERRQ(ierr);
1517   ierr = PetscMemcpy(&ls,&dm,sizeof(dm));CHKERRQ(ierr);
1518   ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr);
1519   ierr = PetscMemcpy(&lA,&A,sizeof(A));CHKERRQ(ierr);
1520   ierr = PetscMemcpy(&lB,&B,sizeof(B));CHKERRQ(ierr);
1521   prhs[0] =  mxCreateDoubleScalar((double)ls);
1522   prhs[1] =  mxCreateDoubleScalar((double)lx);
1523   prhs[2] =  mxCreateDoubleScalar((double)lA);
1524   prhs[3] =  mxCreateDoubleScalar((double)lB);
1525   prhs[4] =  mxCreateString(sctx->jacname);
1526   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscDMComputeJacobianInternal");CHKERRQ(ierr);
1527   *str    =  (MatStructure) mxGetScalar(plhs[0]);
1528   ierr    =  (PetscInt) mxGetScalar(plhs[1]);CHKERRQ(ierr);
1529   mxDestroyArray(prhs[0]);
1530   mxDestroyArray(prhs[1]);
1531   mxDestroyArray(prhs[2]);
1532   mxDestroyArray(prhs[3]);
1533   mxDestroyArray(prhs[4]);
1534   mxDestroyArray(plhs[0]);
1535   mxDestroyArray(plhs[1]);
1536   PetscFunctionReturn(0);
1537 }
1538 
1539 
1540 #undef __FUNCT__
1541 #define __FUNCT__ "DMSetJacobianMatlab"
1542 /*
1543    DMSetJacobianMatlab - Sets the Jacobian function evaluation routine
1544 
1545 */
1546 PetscErrorCode  DMSetJacobianMatlab(DM dm,const char *func)
1547 {
1548   PetscErrorCode    ierr;
1549   DMMatlabContext   *sctx;
1550 
1551   PetscFunctionBegin;
1552   /* currently sctx is memory bleed */
1553   ierr = DMGetContext(dm,(void**)&sctx);CHKERRQ(ierr);
1554   if (!sctx) {
1555     ierr = PetscMalloc(sizeof(DMMatlabContext),&sctx);CHKERRQ(ierr);
1556   }
1557   ierr = PetscStrallocpy(func,&sctx->jacname);CHKERRQ(ierr);
1558   ierr = DMSetContext(dm,sctx);CHKERRQ(ierr);
1559   ierr = DMSetJacobian(dm,DMComputeJacobian_Matlab);CHKERRQ(ierr);
1560   PetscFunctionReturn(0);
1561 }
1562 #endif
1563