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