Actual source code: dm.c

  1: 
  2: #include <private/dmimpl.h>     /*I      "petscdm.h"     I*/

  4: PetscClassId  DM_CLASSID;
  5: PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal;

  9: /*@
 10:   DMCreate - Creates an empty vector object. The type can then be set with DMetType().

 12:    If you never  call DMSetType()  it will generate an 
 13:    error when you try to use the vector.

 15:   Collective on MPI_Comm

 17:   Input Parameter:
 18: . comm - The communicator for the DM object

 20:   Output Parameter:
 21: . dm - The DM object

 23:   Level: beginner

 25: .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE
 26: @*/
 27: PetscErrorCode  DMCreate(MPI_Comm comm,DM *dm)
 28: {
 29:   DM             v;

 34:   *dm = PETSC_NULL;
 35: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
 36:   DMInitializePackage(PETSC_NULL);
 37: #endif

 39:   PetscHeaderCreate(v, _p_DM, struct _DMOps, DM_CLASSID, -1, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);
 40:   PetscMemzero(v->ops, sizeof(struct _DMOps));

 42:   v->ltogmap      = PETSC_NULL;
 43:   v->ltogmapb     = PETSC_NULL;
 44:   v->bs           = 1;

 46:   *dm = v;
 47:   return(0);
 48: }


 53: /*@C
 54:        DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()

 56:    Logically Collective on DMDA

 58:    Input Parameter:
 59: +  da - initial distributed array
 60: .  ctype - the vector type, currently either VECSTANDARD or VECCUSP

 62:    Options Database:
 63: .   -da_vec_type ctype

 65:    Level: intermediate

 67: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType, VecType
 68: @*/
 69: PetscErrorCode  DMSetVecType(DM da,const VecType ctype)
 70: {

 75:   PetscFree(da->vectype);
 76:   PetscStrallocpy(ctype,&da->vectype);
 77:   return(0);
 78: }

 82: /*@C
 83:    DMSetOptionsPrefix - Sets the prefix used for searching for all 
 84:    DMDA options in the database.

 86:    Logically Collective on DMDA

 88:    Input Parameter:
 89: +  da - the DMDA context
 90: -  prefix - the prefix to prepend to all option names

 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.

 96:    Level: advanced

 98: .keywords: DMDA, set, options, prefix, database

100: .seealso: DMSetFromOptions()
101: @*/
102: PetscErrorCode  DMSetOptionsPrefix(DM dm,const char prefix[])
103: {

108:   PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);
109:   return(0);
110: }

114: /*@
115:     DMDestroy - Destroys a vector packer or DMDA.

117:     Collective on DM

119:     Input Parameter:
120: .   dm - the DM object to destroy

122:     Level: developer

124: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()

126: @*/
127: PetscErrorCode  DMDestroy(DM *dm)
128: {
129:   PetscInt       i, cnt = 0;

133:   if (!*dm) return(0);

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:     PetscObjectQuery((PetscObject)(*dm)->x,"DM",&obj);
144:     if (obj == (PetscObject)*dm) cnt++;
145:   }

147:   if (--((PetscObject)(*dm))->refct - cnt > 0) {*dm = 0; return(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) return(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:     VecDestroy(&(*dm)->localin[i]);
158:   }
159:   VecDestroy(&(*dm)->x);
160:   MatFDColoringDestroy(&(*dm)->fd);
161:   DMClearGlobalVectors(*dm);
162:   ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);
163:   ISLocalToGlobalMappingDestroy(&(*dm)->ltogmapb);
164:   PetscFree((*dm)->vectype);
165:   PetscFree((*dm)->mattype);
166:   /* if memory was published with AMS then destroy it */
167:   PetscObjectDepublish(*dm);

169:   (*(*dm)->ops->destroy)(*dm);
170:   PetscFree((*dm)->data);
171:   PetscHeaderDestroy(dm);
172:   return(0);
173: }

177: /*@
178:     DMSetUp - sets up the data structures inside a DM object

180:     Collective on DM

182:     Input Parameter:
183: .   dm - the DM object to setup

185:     Level: developer

187: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()

189: @*/
190: PetscErrorCode  DMSetUp(DM dm)
191: {

195:   if (dm->setupcalled) return(0);
196:   if (dm->ops->setup) {
197:     (*dm->ops->setup)(dm);
198:   }
199:   dm->setupcalled = PETSC_TRUE;
200:   return(0);
201: }

205: /*@
206:     DMSetFromOptions - sets parameters in a DM from the options database

208:     Collective on DM

210:     Input Parameter:
211: .   dm - the DM object to set options for

213:     Options Database:
214: .   -dm_preallocate_only: Only preallocate the matrix for DMGetMatrix(), but do not fill it with zeros

216:     Level: developer

218: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()

220: @*/
221: PetscErrorCode  DMSetFromOptions(DM dm)
222: {
223:   PetscBool      flg1 = PETSC_FALSE,flg;
225:   char           mtype[256] = MATAIJ;

228:   if (dm->ops->setfromoptions) {
229:     (*dm->ops->setfromoptions)(dm);
230:   }
231:   PetscObjectOptionsBegin((PetscObject)dm);
232:     PetscOptionsBool("-dm_view", "Information on DM", "DMView", flg1, &flg1, PETSC_NULL);
233:     PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,PETSC_NULL);
234:     PetscOptionsList("-dm_mat_type","Matrix type","MatSetType",MatList,mtype,mtype,sizeof mtype,&flg);
235:     if (flg) {
236:       PetscFree(dm->mattype);
237:       PetscStrallocpy(mtype,&dm->mattype);
238:     }
239:   PetscOptionsEnd();
240:   if (flg1) {
241:     DMView(dm, PETSC_VIEWER_STDOUT_WORLD);
242:   }
243:   return(0);
244: }

248: /*@C
249:     DMView - Views a vector packer or DMDA.

251:     Collective on DM

253:     Input Parameter:
254: +   dm - the DM object to view
255: -   v - the viewer

257:     Level: developer

259: .seealso DMDestroy(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()

261: @*/
262: PetscErrorCode  DMView(DM dm,PetscViewer v)
263: {

267:  if (!v) {
268:     PetscViewerASCIIGetStdout(((PetscObject)dm)->comm,&v);
269:   }
270:   if (dm->ops->view) {
271:     (*dm->ops->view)(dm,v);
272:   }
273:   return(0);
274: }

278: /*@
279:     DMCreateGlobalVector - Creates a global vector from a DMDA or DMComposite object

281:     Collective on DM

283:     Input Parameter:
284: .   dm - the DM object

286:     Output Parameter:
287: .   vec - the global vector

289:     Level: beginner

291: .seealso DMDestroy(), DMView(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()

293: @*/
294: PetscErrorCode  DMCreateGlobalVector(DM dm,Vec *vec)
295: {

299:   (*dm->ops->createglobalvector)(dm,vec);
300:   return(0);
301: }

305: /*@
306:     DMCreateLocalVector - Creates a local vector from a DMDA or DMComposite object

308:     Not Collective

310:     Input Parameter:
311: .   dm - the DM object

313:     Output Parameter:
314: .   vec - the local vector

316:     Level: beginner

318: .seealso DMDestroy(), DMView(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()

320: @*/
321: PetscErrorCode  DMCreateLocalVector(DM dm,Vec *vec)
322: {

326:   (*dm->ops->createlocalvector)(dm,vec);
327:   return(0);
328: }

332: /*@
333:    DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM.

335:    Collective on DM

337:    Input Parameter:
338: .  dm - the DM that provides the mapping

340:    Output Parameter:
341: .  ltog - the mapping

343:    Level: intermediate

345:    Notes:
346:    This mapping can then be used by VecSetLocalToGlobalMapping() or
347:    MatSetLocalToGlobalMapping().

349: .seealso: DMCreateLocalVector(), DMGetLocalToGlobalMappingBlock()
350: @*/
351: PetscErrorCode  DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog)
352: {

358:   if (!dm->ltogmap) {
359:     if (!dm->ops->createlocaltoglobalmapping) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping");
360:     (*dm->ops->createlocaltoglobalmapping)(dm);
361:   }
362:   *ltog = dm->ltogmap;
363:   return(0);
364: }

368: /*@
369:    DMGetLocalToGlobalMappingBlock - Accesses the blocked local-to-global mapping in a DM.

371:    Collective on DM

373:    Input Parameter:
374: .  da - the distributed array that provides the mapping

376:    Output Parameter:
377: .  ltog - the block mapping

379:    Level: intermediate

381:    Notes:
382:    This mapping can then be used by VecSetLocalToGlobalMappingBlock() or
383:    MatSetLocalToGlobalMappingBlock().

385: .seealso: DMCreateLocalVector(), DMGetLocalToGlobalMapping(), DMGetBlockSize(), VecSetBlockSize(), MatSetBlockSize()
386: @*/
387: PetscErrorCode  DMGetLocalToGlobalMappingBlock(DM dm,ISLocalToGlobalMapping *ltog)
388: {

394:   if (!dm->ltogmapb) {
395:     PetscInt bs;
396:     DMGetBlockSize(dm,&bs);
397:     if (bs > 1) {
398:       if (!dm->ops->createlocaltoglobalmappingblock) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"DM can not create LocalToGlobalMappingBlock");
399:       (*dm->ops->createlocaltoglobalmappingblock)(dm);
400:     } else {
401:       DMGetLocalToGlobalMapping(dm,&dm->ltogmapb);
402:       PetscObjectReference((PetscObject)dm->ltogmapb);
403:     }
404:   }
405:   *ltog = dm->ltogmapb;
406:   return(0);
407: }

411: /*@
412:    DMGetBlockSize - Gets the inherent block size associated with a DM

414:    Not Collective

416:    Input Parameter:
417: .  dm - the DM with block structure

419:    Output Parameter:
420: .  bs - the block size, 1 implies no exploitable block structure

422:    Level: intermediate

424: .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMappingBlock()
425: @*/
426: PetscErrorCode  DMGetBlockSize(DM dm,PetscInt *bs)
427: {
431:   if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet");
432:   *bs = dm->bs;
433:   return(0);
434: }

438: /*@
439:     DMGetInterpolation - Gets interpolation matrix between two DMDA or DMComposite objects

441:     Collective on DM

443:     Input Parameter:
444: +   dm1 - the DM object
445: -   dm2 - the second, finer DM object

447:     Output Parameter:
448: +  mat - the interpolation
449: -  vec - the scaling (optional)

451:     Level: developer

453:     Notes:  For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 
454:         DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.

456:         For DMDA objects you can use this interpolation (more precisely the interpolation from the DMDAGetCoordinateDA()) to interpolate the mesh coordinate vectors
457:         EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
458:    

460: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetColoring(), DMGetMatrix(), DMRefine(), DMCoarsen()

462: @*/
463: PetscErrorCode  DMGetInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec)
464: {

468:   (*dm1->ops->getinterpolation)(dm1,dm2,mat,vec);
469:   return(0);
470: }

474: /*@
475:     DMGetInjection - Gets injection matrix between two DMDA or DMComposite objects

477:     Collective on DM

479:     Input Parameter:
480: +   dm1 - the DM object
481: -   dm2 - the second, finer DM object

483:     Output Parameter:
484: .   ctx - the injection

486:     Level: developer

488:    Notes:  For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 
489:         DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection.

491: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetColoring(), DMGetMatrix(), DMGetInterpolation()

493: @*/
494: PetscErrorCode  DMGetInjection(DM dm1,DM dm2,VecScatter *ctx)
495: {

499:   (*dm1->ops->getinjection)(dm1,dm2,ctx);
500:   return(0);
501: }

505: /*@C
506:     DMGetColoring - Gets coloring for a DMDA or DMComposite

508:     Collective on DM

510:     Input Parameter:
511: +   dm - the DM object
512: .   ctype - IS_COLORING_GHOSTED or IS_COLORING_GLOBAL
513: -   matype - either MATAIJ or MATBAIJ

515:     Output Parameter:
516: .   coloring - the coloring

518:     Level: developer

520: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetMatrix()

522: @*/
523: PetscErrorCode  DMGetColoring(DM dm,ISColoringType ctype,const MatType mtype,ISColoring *coloring)
524: {

528:   if (!dm->ops->getcoloring) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No coloring for this type of DM yet");
529:   (*dm->ops->getcoloring)(dm,ctype,mtype,coloring);
530:   return(0);
531: }

535: /*@C
536:     DMGetMatrix - Gets empty Jacobian for a DMDA or DMComposite

538:     Collective on DM

540:     Input Parameter:
541: +   dm - the DM object
542: -   mtype - Supported types are MATSEQAIJ, MATMPIAIJ, MATSEQBAIJ, MATMPIBAIJ, or
543:             any type which inherits from one of these (such as MATAIJ)

545:     Output Parameter:
546: .   mat - the empty Jacobian 

548:     Level: beginner

550:     Notes: This properly preallocates the number of nonzeros in the sparse matrix so you 
551:        do not need to do it yourself. 

553:        By default it also sets the nonzero structure and puts in the zero entries. To prevent setting 
554:        the nonzero pattern call DMDASetMatPreallocateOnly()

556:        For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used
557:        internally by PETSc.

559:        For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires 
560:        the indices for the global numbering for DMDAs which is complicated.

562: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()

564: @*/
565: PetscErrorCode  DMGetMatrix(DM dm,const MatType mtype,Mat *mat)
566: {

570: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
571:   MatInitializePackage(PETSC_NULL);
572: #endif
575:   if (dm->mattype) {
576:     (*dm->ops->getmatrix)(dm,dm->mattype,mat);
577:   } else {
578:     (*dm->ops->getmatrix)(dm,mtype,mat);
579:   }
580:   return(0);
581: }

585: /*@
586:   DMSetMatrixPreallocateOnly - When DMGetMatrix() is called the matrix will be properly
587:     preallocated but the nonzero structure and zero values will not be set.

589:   Logically Collective on DMDA

591:   Input Parameter:
592: + dm - the DM
593: - only - PETSC_TRUE if only want preallocation

595:   Level: developer
596: .seealso DMGetMatrix()
597: @*/
598: PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
599: {
602:   dm->prealloc_only = only;
603:   return(0);
604: }

608: /*@
609:     DMRefine - Refines a DM object

611:     Collective on DM

613:     Input Parameter:
614: +   dm - the DM object
615: -   comm - the communicator to contain the new DM object (or PETSC_NULL)

617:     Output Parameter:
618: .   dmf - the refined DM

620:     Level: developer

622: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()

624: @*/
625: PetscErrorCode  DMRefine(DM dm,MPI_Comm comm,DM *dmf)
626: {

631:   (*dm->ops->refine)(dm,comm,dmf);
632:   (*dmf)->ops->initialguess = dm->ops->initialguess;
633:   (*dmf)->ops->function     = dm->ops->function;
634:   (*dmf)->ops->functionj    = dm->ops->functionj;
635:   if (dm->ops->jacobian != DMComputeJacobianDefault) {
636:     (*dmf)->ops->jacobian     = dm->ops->jacobian;
637:   }
638:   PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);
639:   (*dmf)->ctx     = dm->ctx;
640:   (*dmf)->levelup = dm->levelup + 1;
641:   return(0);
642: }

646: /*@
647:     DMGetRefineLevel - Get's the number of refinements that have generated this DM.

649:     Not Collective

651:     Input Parameter:
652: .   dm - the DM object

654:     Output Parameter:
655: .   level - number of refinements

657:     Level: developer

659: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()

661: @*/
662: PetscErrorCode  DMGetRefineLevel(DM dm,PetscInt *level)
663: {
666:   *level = dm->levelup;
667:   return(0);
668: }

672: /*@
673:     DMGlobalToLocalBegin - Begins updating local vectors from global vector

675:     Neighbor-wise Collective on DM

677:     Input Parameters:
678: +   dm - the DM object
679: .   g - the global vector
680: .   mode - INSERT_VALUES or ADD_VALUES
681: -   l - the local vector


684:     Level: beginner

686: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()

688: @*/
689: PetscErrorCode  DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
690: {

694:   (*dm->ops->globaltolocalbegin)(dm,g,mode,l);
695:   return(0);
696: }

700: /*@
701:     DMGlobalToLocalEnd - Ends updating local vectors from global vector

703:     Neighbor-wise Collective on DM

705:     Input Parameters:
706: +   dm - the DM object
707: .   g - the global vector
708: .   mode - INSERT_VALUES or ADD_VALUES
709: -   l - the local vector


712:     Level: beginner

714: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()

716: @*/
717: PetscErrorCode  DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
718: {

722:   (*dm->ops->globaltolocalend)(dm,g,mode,l);
723:   return(0);
724: }

728: /*@
729:     DMLocalToGlobalBegin - updates global vectors from local vectors

731:     Neighbor-wise Collective on DM

733:     Input Parameters:
734: +   dm - the DM object
735: .   l - the local vector
736: .   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
737:            base point. 
738: - - the global vector

740:     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
741:            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 
742:            global array to the final global array with VecAXPY().

744:     Level: beginner

746: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()

748: @*/
749: PetscErrorCode  DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
750: {

754:   (*dm->ops->localtoglobalbegin)(dm,l,mode,g);
755:   return(0);
756: }

760: /*@
761:     DMLocalToGlobalEnd - updates global vectors from local vectors

763:     Neighbor-wise Collective on DM

765:     Input Parameters:
766: +   dm - the DM object
767: .   l - the local vector
768: .   mode - INSERT_VALUES or ADD_VALUES
769: -   g - the global vector


772:     Level: beginner

774: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()

776: @*/
777: PetscErrorCode  DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
778: {

782:   (*dm->ops->localtoglobalend)(dm,l,mode,g);
783:   return(0);
784: }

788: /*@
789:     DMComputeJacobianDefault - computes the Jacobian using the DMComputeFunction() if Jacobian computer is not provided

791:     Collective on DM

793:     Input Parameter:
794: +   dm - the DM object 
795: .   x - location to compute Jacobian at; may be ignored for linear problems
796: .   A - matrix that defines the operator for the linear solve
797: -   B - the matrix used to construct the preconditioner

799:     Level: developer

801: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetInitialGuess(), 
802:          DMSetFunction()

804: @*/
805: PetscErrorCode  DMComputeJacobianDefault(DM dm,Vec x,Mat A,Mat B,MatStructure *stflag)
806: {
809:   *stflag = SAME_NONZERO_PATTERN;
810:   MatFDColoringApply(B,dm->fd,x,stflag,dm);
811:   if (A != B) {
812:     MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
813:     MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
814:   }
815:   return(0);
816: }

820: /*@
821:     DMCoarsen - Coarsens a DM object

823:     Collective on DM

825:     Input Parameter:
826: +   dm - the DM object
827: -   comm - the communicator to contain the new DM object (or PETSC_NULL)

829:     Output Parameter:
830: .   dmc - the coarsened DM

832:     Level: developer

834: .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()

836: @*/
837: PetscErrorCode  DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
838: {

842:   (*dm->ops->coarsen)(dm, comm, dmc);
843:   (*dmc)->ops->initialguess = dm->ops->initialguess;
844:   (*dmc)->ops->function     = dm->ops->function;
845:   (*dmc)->ops->functionj    = dm->ops->functionj;
846:   if (dm->ops->jacobian != DMComputeJacobianDefault) {
847:     (*dmc)->ops->jacobian     = dm->ops->jacobian;
848:   }
849:   PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);
850:   (*dmc)->ctx       = dm->ctx;
851:   (*dmc)->leveldown = dm->leveldown + 1;
852:   return(0);
853: }

857: /*@C
858:     DMRefineHierarchy - Refines a DM object, all levels at once

860:     Collective on DM

862:     Input Parameter:
863: +   dm - the DM object
864: -   nlevels - the number of levels of refinement

866:     Output Parameter:
867: .   dmf - the refined DM hierarchy

869:     Level: developer

871: .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()

873: @*/
874: PetscErrorCode  DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
875: {

879:   if (nlevels < 0) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
880:   if (nlevels == 0) return(0);
881:   if (dm->ops->refinehierarchy) {
882:     (*dm->ops->refinehierarchy)(dm,nlevels,dmf);
883:   } else if (dm->ops->refine) {
884:     PetscInt i;

886:     DMRefine(dm,((PetscObject)dm)->comm,&dmf[0]);
887:     for (i=1; i<nlevels; i++) {
888:       DMRefine(dmf[i-1],((PetscObject)dm)->comm,&dmf[i]);
889:     }
890:   } else {
891:     SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
892:   }
893:   return(0);
894: }

898: /*@C
899:     DMCoarsenHierarchy - Coarsens a DM object, all levels at once

901:     Collective on DM

903:     Input Parameter:
904: +   dm - the DM object
905: -   nlevels - the number of levels of coarsening

907:     Output Parameter:
908: .   dmc - the coarsened DM hierarchy

910:     Level: developer

912: .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()

914: @*/
915: PetscErrorCode  DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
916: {

920:   if (nlevels < 0) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
921:   if (nlevels == 0) return(0);
923:   if (dm->ops->coarsenhierarchy) {
924:     (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);
925:   } else if (dm->ops->coarsen) {
926:     PetscInt i;

928:     DMCoarsen(dm,((PetscObject)dm)->comm,&dmc[0]);
929:     for (i=1; i<nlevels; i++) {
930:       DMCoarsen(dmc[i-1],((PetscObject)dm)->comm,&dmc[i]);
931:     }
932:   } else {
933:     SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
934:   }
935:   return(0);
936: }

940: /*@
941:    DMGetAggregates - Gets the aggregates that map between 
942:    grids associated with two DMs.

944:    Collective on DM

946:    Input Parameters:
947: +  dmc - the coarse grid DM
948: -  dmf - the fine grid DM

950:    Output Parameters:
951: .  rest - the restriction matrix (transpose of the projection matrix)

953:    Level: intermediate

955: .keywords: interpolation, restriction, multigrid 

957: .seealso: DMRefine(), DMGetInjection(), DMGetInterpolation()
958: @*/
959: PetscErrorCode  DMGetAggregates(DM dmc, DM dmf, Mat *rest)
960: {

964:   (*dmc->ops->getaggregates)(dmc, dmf, rest);
965:   return(0);
966: }

970: /*@
971:     DMSetApplicationContext - Set a user context into a DM object

973:     Not Collective

975:     Input Parameters:
976: +   dm - the DM object 
977: -   ctx - the user context

979:     Level: intermediate

981: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext()

983: @*/
984: PetscErrorCode  DMSetApplicationContext(DM dm,void *ctx)
985: {
987:   dm->ctx = ctx;
988:   return(0);
989: }

993: /*@
994:     DMGetApplicationContext - Gets a user context from a DM object

996:     Not Collective

998:     Input Parameter:
999: .   dm - the DM object 

1001:     Output Parameter:
1002: .   ctx - the user context

1004:     Level: intermediate

1006: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext()

1008: @*/
1009: PetscErrorCode  DMGetApplicationContext(DM dm,void *ctx)
1010: {
1012:   *(void**)ctx = dm->ctx;
1013:   return(0);
1014: }

1018: /*@C
1019:     DMSetInitialGuess - sets a function to compute an initial guess vector entries for the solvers

1021:     Logically Collective on DM

1023:     Input Parameter:
1024: +   dm - the DM object to destroy
1025: -   f - the function to compute the initial guess

1027:     Level: intermediate

1029: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian()

1031: @*/
1032: PetscErrorCode  DMSetInitialGuess(DM dm,PetscErrorCode (*f)(DM,Vec))
1033: {
1035:   dm->ops->initialguess = f;
1036:   return(0);
1037: }

1041: /*@C
1042:     DMSetFunction - sets a function to compute the right hand side vector entries for the KSP solver or nonlinear function for SNES

1044:     Logically Collective on DM

1046:     Input Parameter:
1047: +   dm - the DM object 
1048: -   f - the function to compute (use PETSC_NULL to cancel a previous function that was set)

1050:     Level: intermediate

1052:     Notes: This sets both the function for function evaluations and the function used to compute Jacobians via finite differences if no Jacobian 
1053:            computer is provided with DMSetJacobian(). Canceling cancels the function, but not the function used to compute the Jacobian.

1055: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetInitialGuess(),
1056:          DMSetJacobian()

1058: @*/
1059: PetscErrorCode  DMSetFunction(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
1060: {
1062:   dm->ops->function = f;
1063:   if (f) {
1064:     dm->ops->functionj = f;
1065:   }
1066:   return(0);
1067: }

1071: /*@C
1072:     DMSetJacobian - sets a function to compute the matrix entries for the KSP solver or Jacobian for SNES

1074:     Logically Collective on DM

1076:     Input Parameter:
1077: +   dm - the DM object to destroy
1078: -   f - the function to compute the matrix entries

1080:     Level: intermediate

1082: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetInitialGuess(), 
1083:          DMSetFunction()

1085: @*/
1086: PetscErrorCode  DMSetJacobian(DM dm,PetscErrorCode (*f)(DM,Vec,Mat,Mat,MatStructure*))
1087: {
1089:   dm->ops->jacobian = f;
1090:   return(0);
1091: }

1095: /*@
1096:     DMComputeInitialGuess - computes an initial guess vector entries for the KSP solvers

1098:     Collective on DM

1100:     Input Parameter:
1101: +   dm - the DM object to destroy
1102: -   x - the vector to hold the initial guess values

1104:     Level: developer

1106: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetRhs(), DMSetMat()

1108: @*/
1109: PetscErrorCode  DMComputeInitialGuess(DM dm,Vec x)
1110: {
1113:   if (!dm->ops->initialguess) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to provide function with DMSetInitialGuess()");
1114:   (*dm->ops->initialguess)(dm,x);
1115:   return(0);
1116: }

1120: /*@
1121:     DMHasInitialGuess - does the DM object have an initial guess function

1123:     Not Collective

1125:     Input Parameter:
1126: .   dm - the DM object to destroy

1128:     Output Parameter:
1129: .   flg - PETSC_TRUE if function exists

1131:     Level: developer

1133: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian()

1135: @*/
1136: PetscErrorCode  DMHasInitialGuess(DM dm,PetscBool  *flg)
1137: {
1139:   *flg =  (dm->ops->initialguess) ? PETSC_TRUE : PETSC_FALSE;
1140:   return(0);
1141: }

1145: /*@
1146:     DMHasFunction - does the DM object have a function

1148:     Not Collective

1150:     Input Parameter:
1151: .   dm - the DM object to destroy

1153:     Output Parameter:
1154: .   flg - PETSC_TRUE if function exists

1156:     Level: developer

1158: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian()

1160: @*/
1161: PetscErrorCode  DMHasFunction(DM dm,PetscBool  *flg)
1162: {
1164:   *flg =  (dm->ops->function) ? PETSC_TRUE : PETSC_FALSE;
1165:   return(0);
1166: }

1170: /*@
1171:     DMHasJacobian - does the DM object have a matrix function

1173:     Not Collective

1175:     Input Parameter:
1176: .   dm - the DM object to destroy

1178:     Output Parameter:
1179: .   flg - PETSC_TRUE if function exists

1181:     Level: developer

1183: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian()

1185: @*/
1186: PetscErrorCode  DMHasJacobian(DM dm,PetscBool  *flg)
1187: {
1189:   *flg =  (dm->ops->jacobian) ? PETSC_TRUE : PETSC_FALSE;
1190:   return(0);
1191: }

1195: /*@
1196:     DMComputeFunction - computes the right hand side vector entries for the KSP solver or nonlinear function for SNES

1198:     Collective on DM

1200:     Input Parameter:
1201: +   dm - the DM object to destroy
1202: .   x - the location where the function is evaluationed, may be ignored for linear problems
1203: -   b - the vector to hold the right hand side entries

1205:     Level: developer

1207: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetInitialGuess(),
1208:          DMSetJacobian()

1210: @*/
1211: PetscErrorCode  DMComputeFunction(DM dm,Vec x,Vec b)
1212: {
1215:   if (!dm->ops->function) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to provide function with DMSetFunction()");
1216:   PetscStackPush("DM user function");
1217:   (*dm->ops->function)(dm,x,b);
1218:   PetscStackPop;
1219:   return(0);
1220: }


1225: /*@
1226:     DMComputeJacobian - compute the matrix entries for the solver

1228:     Collective on DM

1230:     Input Parameter:
1231: +   dm - the DM object 
1232: .   x - location to compute Jacobian at; will be PETSC_NULL for linear problems, for nonlinear problems if not provided then pulled from DM
1233: .   A - matrix that defines the operator for the linear solve
1234: -   B - the matrix used to construct the preconditioner

1236:     Level: developer

1238: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetInitialGuess(), 
1239:          DMSetFunction()

1241: @*/
1242: PetscErrorCode  DMComputeJacobian(DM dm,Vec x,Mat A,Mat B,MatStructure *stflag)
1243: {

1247:   if (!dm->ops->jacobian) {
1248:     ISColoring     coloring;
1249:     MatFDColoring  fd;

1251:     DMGetColoring(dm,IS_COLORING_GLOBAL,MATAIJ,&coloring);
1252:     MatFDColoringCreate(B,coloring,&fd);
1253:     ISColoringDestroy(&coloring);
1254:     MatFDColoringSetFunction(fd,(PetscErrorCode (*)(void))dm->ops->functionj,dm);
1255:     PetscObjectSetOptionsPrefix((PetscObject)fd,((PetscObject)dm)->prefix);
1256:     MatFDColoringSetFromOptions(fd);

1258:     dm->fd = fd;
1259:     dm->ops->jacobian = DMComputeJacobianDefault;

1261:     /* don't know why this is needed */
1262:     PetscObjectDereference((PetscObject)dm);
1263:   }
1264:   if (!x) x = dm->x;
1265:   (*dm->ops->jacobian)(dm,x,A,B,stflag);

1267:   /* if matrix depends on x; i.e. nonlinear problem, keep copy of input vector since needed by multigrid methods to generate coarse grid matrices */
1268:   if (x) {
1269:     if (!dm->x) {
1270:       DMCreateGlobalVector(dm,&dm->x);
1271:     }
1272:     VecCopy(x,dm->x);
1273:   }
1274:   if (A != B) {
1275:     MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
1276:     MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
1277:   }
1278:   return(0);
1279: }


1282: PetscFList DMList                       = PETSC_NULL;
1283: PetscBool  DMRegisterAllCalled          = PETSC_FALSE;

1287: /*@C
1288:   DMSetType - Builds a DM, for a particular DM implementation.

1290:   Collective on DM

1292:   Input Parameters:
1293: + dm     - The DM object
1294: - method - The name of the DM type

1296:   Options Database Key:
1297: . -dm_type <type> - Sets the DM type; use -help for a list of available types

1299:   Notes:
1300:   See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).

1302:   Level: intermediate

1304: .keywords: DM, set, type
1305: .seealso: DMGetType(), DMCreate()
1306: @*/
1307: PetscErrorCode  DMSetType(DM dm, const DMType method)
1308: {
1309:   PetscErrorCode (*r)(DM);
1310:   PetscBool      match;

1315:   PetscTypeCompare((PetscObject) dm, method, &match);
1316:   if (match) return(0);

1318:   if (!DMRegisterAllCalled) {DMRegisterAll(PETSC_NULL);}
1319:   PetscFListFind(DMList, ((PetscObject)dm)->comm, method,PETSC_TRUE,(void (**)(void)) &r);
1320:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);

1322:   if (dm->ops->destroy) {
1323:     (*dm->ops->destroy)(dm);
1324:   }
1325:   (*r)(dm);
1326:   PetscObjectChangeTypeName((PetscObject)dm,method);
1327:   return(0);
1328: }

1332: /*@C
1333:   DMGetType - Gets the DM type name (as a string) from the DM.

1335:   Not Collective

1337:   Input Parameter:
1338: . dm  - The DM

1340:   Output Parameter:
1341: . type - The DM type name

1343:   Level: intermediate

1345: .keywords: DM, get, type, name
1346: .seealso: DMSetType(), DMCreate()
1347: @*/
1348: PetscErrorCode  DMGetType(DM dm, const DMType *type)
1349: {

1355:   if (!DMRegisterAllCalled) {
1356:     DMRegisterAll(PETSC_NULL);
1357:   }
1358:   *type = ((PetscObject)dm)->type_name;
1359:   return(0);
1360: }

1364: /*@C
1365:   DMConvert - Converts a DM to another DM, either of the same or different type.

1367:   Collective on DM

1369:   Input Parameters:
1370: + dm - the DM
1371: - newtype - new DM type (use "same" for the same type)

1373:   Output Parameter:
1374: . M - pointer to new DM

1376:   Notes:
1377:   Cannot be used to convert a sequential DM to parallel or parallel to sequential,
1378:   the MPI communicator of the generated DM is always the same as the communicator
1379:   of the input DM.

1381:   Level: intermediate

1383: .seealso: DMCreate()
1384: @*/
1385: PetscErrorCode DMConvert(DM dm, const DMType newtype, DM *M)
1386: {
1387:   DM             B;
1388:   char           convname[256];
1389:   PetscBool      sametype, issame;

1396:   PetscTypeCompare((PetscObject) dm, newtype, &sametype);
1397:   PetscStrcmp(newtype, "same", &issame);
1398:   {
1399:     PetscErrorCode (*conv)(DM, const DMType, DM *) = PETSC_NULL;

1401:     /*
1402:        Order of precedence:
1403:        1) See if a specialized converter is known to the current DM.
1404:        2) See if a specialized converter is known to the desired DM class.
1405:        3) See if a good general converter is registered for the desired class
1406:        4) See if a good general converter is known for the current matrix.
1407:        5) Use a really basic converter.
1408:     */

1410:     /* 1) See if a specialized converter is known to the current DM and the desired class */
1411:     PetscStrcpy(convname,"DMConvert_");
1412:     PetscStrcat(convname,((PetscObject) dm)->type_name);
1413:     PetscStrcat(convname,"_");
1414:     PetscStrcat(convname,newtype);
1415:     PetscStrcat(convname,"_C");
1416:     PetscObjectQueryFunction((PetscObject)dm,convname,(void (**)(void))&conv);
1417:     if (conv) goto foundconv;

1419:     /* 2)  See if a specialized converter is known to the desired DM class. */
1420:     DMCreate(((PetscObject) dm)->comm, &B);
1421:     DMSetType(B, newtype);
1422:     PetscStrcpy(convname,"DMConvert_");
1423:     PetscStrcat(convname,((PetscObject) dm)->type_name);
1424:     PetscStrcat(convname,"_");
1425:     PetscStrcat(convname,newtype);
1426:     PetscStrcat(convname,"_C");
1427:     PetscObjectQueryFunction((PetscObject)B,convname,(void (**)(void))&conv);
1428:     if (conv) {
1429:       DMDestroy(&B);
1430:       goto foundconv;
1431:     }

1433: #if 0
1434:     /* 3) See if a good general converter is registered for the desired class */
1435:     conv = B->ops->convertfrom;
1436:     DMDestroy(&B);
1437:     if (conv) goto foundconv;

1439:     /* 4) See if a good general converter is known for the current matrix */
1440:     if (dm->ops->convert) {
1441:       conv = dm->ops->convert;
1442:     }
1443:     if (conv) goto foundconv;
1444: #endif

1446:     /* 5) Use a really basic converter. */
1447:     SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);

1449:     foundconv:
1450:     PetscLogEventBegin(DM_Convert,dm,0,0,0);
1451:     (*conv)(dm,newtype,M);
1452:     PetscLogEventEnd(DM_Convert,dm,0,0,0);
1453:   }
1454:   PetscObjectStateIncrease((PetscObject) *M);
1455:   return(0);
1456: }

1458: /*--------------------------------------------------------------------------------------------------------------------*/

1462: /*@C
1463:   DMRegister - See DMRegisterDynamic()

1465:   Level: advanced
1466: @*/
1467: PetscErrorCode  DMRegister(const char sname[], const char path[], const char name[], PetscErrorCode (*function)(DM))
1468: {
1469:   char fullname[PETSC_MAX_PATH_LEN];

1473:   PetscStrcpy(fullname, path);
1474:   PetscStrcat(fullname, ":");
1475:   PetscStrcat(fullname, name);
1476:   PetscFListAdd(&DMList, sname, fullname, (void (*)(void)) function);
1477:   return(0);
1478: }


1481: /*--------------------------------------------------------------------------------------------------------------------*/
1484: /*@C
1485:    DMRegisterDestroy - Frees the list of DM methods that were registered by DMRegister()/DMRegisterDynamic().

1487:    Not Collective

1489:    Level: advanced

1491: .keywords: DM, register, destroy
1492: .seealso: DMRegister(), DMRegisterAll(), DMRegisterDynamic()
1493: @*/
1494: PetscErrorCode  DMRegisterDestroy(void)
1495: {

1499:   PetscFListDestroy(&DMList);
1500:   DMRegisterAllCalled = PETSC_FALSE;
1501:   return(0);
1502: }

1504: #if defined(PETSC_HAVE_MATLAB_ENGINE)
1505: #include <mex.h>

1507: typedef struct {char *funcname; char *jacname; mxArray *ctx;} DMMatlabContext;

1511: /*
1512:    DMComputeFunction_Matlab - Calls the function that has been set with
1513:                          DMSetFunctionMatlab().  

1515:    For linear problems x is null
1516:    
1517: .seealso: DMSetFunction(), DMGetFunction()
1518: */
1519: PetscErrorCode  DMComputeFunction_Matlab(DM dm,Vec x,Vec y)
1520: {
1521:   PetscErrorCode    ierr;
1522:   DMMatlabContext   *sctx;
1523:   int               nlhs = 1,nrhs = 4;
1524:   mxArray            *plhs[1],*prhs[4];
1525:   long long int     lx = 0,ly = 0,ls = 0;
1526: 

1532:   /* call Matlab function in ctx with arguments x and y */
1533:   DMGetApplicationContext(dm,&sctx);
1534:   PetscMemcpy(&ls,&dm,sizeof(dm));
1535:   PetscMemcpy(&lx,&x,sizeof(x));
1536:   PetscMemcpy(&ly,&y,sizeof(y));
1537:   prhs[0] =  mxCreateDoubleScalar((double)ls);
1538:   prhs[1] =  mxCreateDoubleScalar((double)lx);
1539:   prhs[2] =  mxCreateDoubleScalar((double)ly);
1540:   prhs[3] =  mxCreateString(sctx->funcname);
1541:    mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscDMComputeFunctionInternal");
1542:    mxGetScalar(plhs[0]);
1543:   mxDestroyArray(prhs[0]);
1544:   mxDestroyArray(prhs[1]);
1545:   mxDestroyArray(prhs[2]);
1546:   mxDestroyArray(prhs[3]);
1547:   mxDestroyArray(plhs[0]);
1548:   return(0);
1549: }


1554: /*
1555:    DMSetFunctionMatlab - Sets the function evaluation routine 

1557: */
1558: PetscErrorCode  DMSetFunctionMatlab(DM dm,const char *func)
1559: {
1560:   PetscErrorCode    ierr;
1561:   DMMatlabContext   *sctx;

1564:   /* currently sctx is memory bleed */
1565:   DMGetApplicationContext(dm,&sctx);
1566:   if (!sctx) {
1567:     PetscMalloc(sizeof(DMMatlabContext),&sctx);
1568:   }
1569:   PetscStrallocpy(func,&sctx->funcname);
1570:   DMSetApplicationContext(dm,sctx);
1571:   DMSetFunction(dm,DMComputeFunction_Matlab);
1572:   return(0);
1573: }

1577: /*
1578:    DMComputeJacobian_Matlab - Calls the function that has been set with
1579:                          DMSetJacobianMatlab().  

1581:    For linear problems x is null
1582:    
1583: .seealso: DMSetFunction(), DMGetFunction()
1584: */
1585: PetscErrorCode  DMComputeJacobian_Matlab(DM dm,Vec x,Mat A,Mat B,MatStructure *str)
1586: {
1587:   PetscErrorCode    ierr;
1588:   DMMatlabContext   *sctx;
1589:   int               nlhs = 2,nrhs = 5;
1590:   mxArray            *plhs[2],*prhs[5];
1591:   long long int     lx = 0,lA = 0,lB = 0,ls = 0;
1592: 

1597:   /* call MATLAB function in ctx with arguments x, A, and B */
1598:   DMGetApplicationContext(dm,&sctx);
1599:   PetscMemcpy(&ls,&dm,sizeof(dm));
1600:   PetscMemcpy(&lx,&x,sizeof(x));
1601:   PetscMemcpy(&lA,&A,sizeof(A));
1602:   PetscMemcpy(&lB,&B,sizeof(B));
1603:   prhs[0] =  mxCreateDoubleScalar((double)ls);
1604:   prhs[1] =  mxCreateDoubleScalar((double)lx);
1605:   prhs[2] =  mxCreateDoubleScalar((double)lA);
1606:   prhs[3] =  mxCreateDoubleScalar((double)lB);
1607:   prhs[4] =  mxCreateString(sctx->jacname);
1608:    mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscDMComputeJacobianInternal");
1609:   *str    =  (MatStructure) mxGetScalar(plhs[0]);
1610:    (PetscInt) mxGetScalar(plhs[1]);
1611:   mxDestroyArray(prhs[0]);
1612:   mxDestroyArray(prhs[1]);
1613:   mxDestroyArray(prhs[2]);
1614:   mxDestroyArray(prhs[3]);
1615:   mxDestroyArray(prhs[4]);
1616:   mxDestroyArray(plhs[0]);
1617:   mxDestroyArray(plhs[1]);
1618:   return(0);
1619: }


1624: /*
1625:    DMSetJacobianMatlab - Sets the Jacobian function evaluation routine 

1627: */
1628: PetscErrorCode  DMSetJacobianMatlab(DM dm,const char *func)
1629: {
1630:   PetscErrorCode    ierr;
1631:   DMMatlabContext   *sctx;

1634:   /* currently sctx is memory bleed */
1635:   DMGetApplicationContext(dm,&sctx);
1636:   if (!sctx) {
1637:     PetscMalloc(sizeof(DMMatlabContext),&sctx);
1638:   }
1639:   PetscStrallocpy(func,&sctx->jacname);
1640:   DMSetApplicationContext(dm,sctx);
1641:   DMSetJacobian(dm,DMComputeJacobian_Matlab);
1642:   return(0);
1643: }
1644: #endif

1648: /*@C
1649:   DMLoad - Loads a DM that has been stored in binary or HDF5 format
1650:   with DMView().

1652:   Collective on PetscViewer 

1654:   Input Parameters:
1655: + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
1656:            some related function before a call to DMLoad(). 
1657: - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
1658:            HDF5 file viewer, obtained from PetscViewerHDF5Open()

1660:    Level: intermediate

1662:   Notes:
1663:   Defaults to the DM DA.

1665:   Notes for advanced users:
1666:   Most users should not need to know the details of the binary storage
1667:   format, since DMLoad() and DMView() completely hide these details.
1668:   But for anyone who's interested, the standard binary matrix storage
1669:   format is  
1670: .vb
1671:      has not yet been determined
1672: .ve

1674:    In addition, PETSc automatically does the byte swapping for
1675: machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1676: linux, Windows and the paragon; thus if you write your own binary
1677: read/write routines you have to swap the bytes; see PetscBinaryRead()
1678: and PetscBinaryWrite() to see how this may be done.

1680:   Concepts: vector^loading from file

1682: .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 
1683: @*/
1684: PetscErrorCode  DMLoad(DM newdm, PetscViewer viewer)
1685: {


1692:   if (!((PetscObject)newdm)->type_name) {
1693:     DMSetType(newdm, DMDA);
1694:   }
1695:   (*newdm->ops->load)(newdm,viewer);
1696:   return(0);
1697: }