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