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